Coverage Report

Created: 2024-05-20 06:23

/src/mupdf/thirdparty/mujs/jsbuiltin.c
Line
Count
Source (jump to first uncovered line)
1
#include "jsi.h"
2
#include "regexp.h"
3
4
static void jsB_globalf(js_State *J, const char *name, js_CFunction cfun, int n)
5
0
{
6
0
  js_newcfunction(J, cfun, name, n);
7
0
  js_defglobal(J, name, JS_DONTENUM);
8
0
}
9
10
void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n)
11
0
{
12
0
  const char *pname = strrchr(name, '.');
13
0
  pname = pname ? pname + 1 : name;
14
0
  js_newcfunction(J, cfun, name, n);
15
0
  js_defproperty(J, -2, pname, JS_DONTENUM);
16
0
}
17
18
void jsB_propn(js_State *J, const char *name, double number)
19
0
{
20
0
  js_pushnumber(J, number);
21
0
  js_defproperty(J, -2, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF);
22
0
}
23
24
void jsB_props(js_State *J, const char *name, const char *string)
25
0
{
26
0
  js_pushliteral(J, string);
27
0
  js_defproperty(J, -2, name, JS_DONTENUM);
28
0
}
29
30
static void jsB_parseInt(js_State *J)
31
0
{
32
0
  const char *s = js_tostring(J, 1);
33
0
  int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 0;
34
0
  double sign = 1;
35
0
  double n;
36
0
  char *e;
37
38
0
  while (jsY_iswhite(*s) || jsY_isnewline(*s))
39
0
    ++s;
40
0
  if (*s == '-') {
41
0
    ++s;
42
0
    sign = -1;
43
0
  } else if (*s == '+') {
44
0
    ++s;
45
0
  }
46
0
  if (radix == 0) {
47
0
    radix = 10;
48
0
    if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
49
0
      s += 2;
50
0
      radix = 16;
51
0
    }
52
0
  } else if (radix < 2 || radix > 36) {
53
0
    js_pushnumber(J, NAN);
54
0
    return;
55
0
  }
56
0
  n = js_strtol(s, &e, radix);
57
0
  if (s == e)
58
0
    js_pushnumber(J, NAN);
59
0
  else
60
0
    js_pushnumber(J, n * sign);
61
0
}
62
63
static void jsB_parseFloat(js_State *J)
64
0
{
65
0
  const char *s = js_tostring(J, 1);
66
0
  char *e;
67
0
  double n;
68
69
0
  while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
70
0
  if (!strncmp(s, "Infinity", 8))
71
0
    js_pushnumber(J, INFINITY);
72
0
  else if (!strncmp(s, "+Infinity", 9))
73
0
    js_pushnumber(J, INFINITY);
74
0
  else if (!strncmp(s, "-Infinity", 9))
75
0
    js_pushnumber(J, -INFINITY);
76
0
  else {
77
0
    n = js_stringtofloat(s, &e);
78
0
    if (e == s)
79
0
      js_pushnumber(J, NAN);
80
0
    else
81
0
      js_pushnumber(J, n);
82
0
  }
83
0
}
84
85
static void jsB_isNaN(js_State *J)
86
0
{
87
0
  double n = js_tonumber(J, 1);
88
0
  js_pushboolean(J, isnan(n));
89
0
}
90
91
static void jsB_isFinite(js_State *J)
92
0
{
93
0
  double n = js_tonumber(J, 1);
94
0
  js_pushboolean(J, isfinite(n));
95
0
}
96
97
static void Encode(js_State *J, const char *str_, const char *unescaped)
98
0
{
99
  /* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
100
0
  const char * volatile str = str_;
101
0
  js_Buffer *sb = NULL;
102
103
0
  static const char *HEX = "0123456789ABCDEF";
104
105
0
  if (js_try(J)) {
106
0
    js_free(J, sb);
107
0
    js_throw(J);
108
0
  }
109
110
0
  while (*str) {
111
0
    int c = (unsigned char) *str++;
112
0
    if (strchr(unescaped, c))
113
0
      js_putc(J, &sb, c);
114
0
    else {
115
0
      js_putc(J, &sb, '%');
116
0
      js_putc(J, &sb, HEX[(c >> 4) & 0xf]);
117
0
      js_putc(J, &sb, HEX[c & 0xf]);
118
0
    }
119
0
  }
120
0
  js_putc(J, &sb, 0);
121
122
0
  js_pushstring(J, sb ? sb->s : "");
123
0
  js_endtry(J);
124
0
  js_free(J, sb);
125
0
}
126
127
static void Decode(js_State *J, const char *str_, const char *reserved)
128
0
{
129
  /* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
130
0
  const char * volatile str = str_;
131
0
  js_Buffer *sb = NULL;
132
0
  int a, b;
133
134
0
  if (js_try(J)) {
135
0
    js_free(J, sb);
136
0
    js_throw(J);
137
0
  }
138
139
0
  while (*str) {
140
0
    int c = (unsigned char) *str++;
141
0
    if (c != '%')
142
0
      js_putc(J, &sb, c);
143
0
    else {
144
0
      if (!str[0] || !str[1])
145
0
        js_urierror(J, "truncated escape sequence");
146
0
      a = *str++;
147
0
      b = *str++;
148
0
      if (!jsY_ishex(a) || !jsY_ishex(b))
149
0
        js_urierror(J, "invalid escape sequence");
150
0
      c = jsY_tohex(a) << 4 | jsY_tohex(b);
151
0
      if (!strchr(reserved, c))
152
0
        js_putc(J, &sb, c);
153
0
      else {
154
0
        js_putc(J, &sb, '%');
155
0
        js_putc(J, &sb, a);
156
0
        js_putc(J, &sb, b);
157
0
      }
158
0
    }
159
0
  }
160
0
  js_putc(J, &sb, 0);
161
162
0
  js_pushstring(J, sb ? sb->s : "");
163
0
  js_endtry(J);
164
0
  js_free(J, sb);
165
0
}
166
167
0
#define URIRESERVED ";/?:@&=+$,"
168
0
#define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
169
#define URIDIGIT "0123456789"
170
0
#define URIMARK "-_.!~*'()"
171
0
#define URIUNESCAPED URIALPHA URIDIGIT URIMARK
172
173
static void jsB_decodeURI(js_State *J)
174
0
{
175
0
  Decode(J, js_tostring(J, 1), URIRESERVED "#");
176
0
}
177
178
static void jsB_decodeURIComponent(js_State *J)
179
0
{
180
0
  Decode(J, js_tostring(J, 1), "");
181
0
}
182
183
static void jsB_encodeURI(js_State *J)
184
0
{
185
0
  Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
186
0
}
187
188
static void jsB_encodeURIComponent(js_State *J)
189
0
{
190
0
  Encode(J, js_tostring(J, 1), URIUNESCAPED);
191
0
}
192
193
void jsB_init(js_State *J)
194
0
{
195
  /* Create the prototype objects here, before the constructors */
196
0
  J->Object_prototype = jsV_newobject(J, JS_COBJECT, NULL);
197
0
  J->Array_prototype = jsV_newobject(J, JS_CARRAY, J->Object_prototype);
198
0
  J->Function_prototype = jsV_newobject(J, JS_CCFUNCTION, J->Object_prototype);
199
0
  J->Boolean_prototype = jsV_newobject(J, JS_CBOOLEAN, J->Object_prototype);
200
0
  J->Number_prototype = jsV_newobject(J, JS_CNUMBER, J->Object_prototype);
201
0
  J->String_prototype = jsV_newobject(J, JS_CSTRING, J->Object_prototype);
202
0
  J->Date_prototype = jsV_newobject(J, JS_CDATE, J->Object_prototype);
203
204
0
  J->RegExp_prototype = jsV_newobject(J, JS_CREGEXP, J->Object_prototype);
205
0
  J->RegExp_prototype->u.r.prog = js_regcompx(J->alloc, J->actx, "(?:)", 0, NULL);
206
0
  J->RegExp_prototype->u.r.source = js_strdup(J, "(?:)");
207
208
  /* All the native error types */
209
0
  J->Error_prototype = jsV_newobject(J, JS_CERROR, J->Object_prototype);
210
0
  J->EvalError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
211
0
  J->RangeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
212
0
  J->ReferenceError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
213
0
  J->SyntaxError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
214
0
  J->TypeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
215
0
  J->URIError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
216
217
  /* Create the constructors and fill out the prototype objects */
218
0
  jsB_initobject(J);
219
0
  jsB_initarray(J);
220
0
  jsB_initfunction(J);
221
0
  jsB_initboolean(J);
222
0
  jsB_initnumber(J);
223
0
  jsB_initstring(J);
224
0
  jsB_initregexp(J);
225
0
  jsB_initdate(J);
226
0
  jsB_initerror(J);
227
0
  jsB_initmath(J);
228
0
  jsB_initjson(J);
229
230
  /* Initialize the global object */
231
0
  js_pushnumber(J, NAN);
232
0
  js_defglobal(J, "NaN", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
233
234
0
  js_pushnumber(J, INFINITY);
235
0
  js_defglobal(J, "Infinity", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
236
237
0
  js_pushundefined(J);
238
0
  js_defglobal(J, "undefined", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
239
240
0
  jsB_globalf(J, "parseInt", jsB_parseInt, 1);
241
0
  jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
242
0
  jsB_globalf(J, "isNaN", jsB_isNaN, 1);
243
0
  jsB_globalf(J, "isFinite", jsB_isFinite, 1);
244
245
0
  jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
246
0
  jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
247
0
  jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
248
0
  jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
249
0
}