mini_racer 0.17.0.pre9 → 0.17.0.pre11
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6851fdd7226dd520cf865af8b60e64b3456a0b0cfd31a22d4f275495c8f42aef
|
4
|
+
data.tar.gz: ffd5db728de9571a2b7e7d83348a95b658809d36f869050338c1f5b0a814146b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76e7edac2249f6aa850bd03f1a7d4c353095f4e3f0a89466c83763f945de44ac68881b57d5b784ac7b6391dd467812a7d27eeeba98ba13624f60dbe4e1db70ab
|
7
|
+
data.tar.gz: 9519ee4b2601ab14a0a1898518bdcda5f318b66b4b4631d7881c2e83ea656c461cbf3fa38682d8702234e01d1cad7c2358125c9b4689333db686ca7207b27fc0
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
- 0.17.0.pre11 - 21-01-2025
|
2
|
+
- Corrected encoding bug with deserialization of strings - Ben Noordhuis
|
3
|
+
|
4
|
+
- 0.17.0.pre10 - 20-01-2025
|
5
|
+
- Added back support for partially deserialized objects (objects that do not translate across boundaries are returned as Error properties) - Ben Noordhuis
|
6
|
+
|
1
7
|
- 0.17.0.pre9 - 13-01-2025
|
2
8
|
- For backwards compatibility convert v8 return values to UTF-8 (invalidly encoded string still get returned using V8 encoding)
|
3
9
|
|
@@ -171,13 +171,14 @@ static void *rendezvous_callback(void *arg);
|
|
171
171
|
typedef struct State
|
172
172
|
{
|
173
173
|
VALUE a, b;
|
174
|
+
uint8_t verbatim_keys:1;
|
174
175
|
} State;
|
175
176
|
|
176
177
|
// note: must be stack-allocated or VALUEs won't be visible to ruby's GC
|
177
178
|
typedef struct DesCtx
|
178
179
|
{
|
179
180
|
State *tos;
|
180
|
-
VALUE refs; // array
|
181
|
+
VALUE refs; // object refs array
|
181
182
|
uint8_t transcode_latin1:1;
|
182
183
|
char err[64];
|
183
184
|
State stack[512];
|
@@ -199,7 +200,7 @@ static void DesCtx_init(DesCtx *c)
|
|
199
200
|
{
|
200
201
|
c->tos = c->stack;
|
201
202
|
c->refs = rb_ary_new();
|
202
|
-
*c->tos = (State){Qundef, Qundef};
|
203
|
+
*c->tos = (State){Qundef, Qundef, /*verbatim_keys*/0};
|
203
204
|
*c->err = '\0';
|
204
205
|
c->transcode_latin1 = 1; // convert to utf8
|
205
206
|
}
|
@@ -220,7 +221,8 @@ static void put(DesCtx *c, VALUE v)
|
|
220
221
|
if (*b == Qundef) {
|
221
222
|
*b = v;
|
222
223
|
} else {
|
223
|
-
|
224
|
+
if (!c->tos->verbatim_keys)
|
225
|
+
*b = rb_funcall(*b, rb_intern("to_s"), 0);
|
224
226
|
rb_hash_aset(*a, *b, v);
|
225
227
|
*b = Qundef;
|
226
228
|
}
|
@@ -242,7 +244,7 @@ static void push(DesCtx *c, VALUE v)
|
|
242
244
|
snprintf(c->err, sizeof(c->err), "stack overflow");
|
243
245
|
return;
|
244
246
|
}
|
245
|
-
*++c->tos = (State){v, Qundef};
|
247
|
+
*++c->tos = (State){v, Qundef, /*verbatim_keys*/0};
|
246
248
|
rb_ary_push(c->refs, v);
|
247
249
|
}
|
248
250
|
|
@@ -337,13 +339,24 @@ static VALUE str_encode_bang(VALUE v)
|
|
337
339
|
|
338
340
|
static void des_string8(void *arg, const uint8_t *s, size_t n)
|
339
341
|
{
|
342
|
+
rb_encoding *e;
|
340
343
|
DesCtx *c;
|
341
344
|
VALUE v;
|
342
345
|
|
343
346
|
c = arg;
|
344
|
-
|
345
|
-
|
347
|
+
if (*c->err)
|
348
|
+
return;
|
349
|
+
if (c->transcode_latin1) {
|
350
|
+
e = rb_enc_find("ISO-8859-1"); // TODO cache?
|
351
|
+
if (!e) {
|
352
|
+
snprintf(c->err, sizeof(c->err), "no ISO-8859-1 encoding");
|
353
|
+
return;
|
354
|
+
}
|
355
|
+
v = rb_enc_str_new((char *)s, n, e);
|
346
356
|
v = str_encode_bang(v); // cannot fail
|
357
|
+
} else {
|
358
|
+
v = rb_enc_str_new((char *)s, n, rb_ascii8bit_encoding());
|
359
|
+
}
|
347
360
|
put(c, v);
|
348
361
|
}
|
349
362
|
|
@@ -426,6 +439,20 @@ static void des_object_end(void *arg)
|
|
426
439
|
pop(arg);
|
427
440
|
}
|
428
441
|
|
442
|
+
static void des_map_begin(void *arg)
|
443
|
+
{
|
444
|
+
DesCtx *c;
|
445
|
+
|
446
|
+
c = arg;
|
447
|
+
push(c, rb_hash_new());
|
448
|
+
c->tos->verbatim_keys = 1; // don't stringify or intern keys
|
449
|
+
}
|
450
|
+
|
451
|
+
static void des_map_end(void *arg)
|
452
|
+
{
|
453
|
+
pop(arg);
|
454
|
+
}
|
455
|
+
|
429
456
|
static void des_object_ref(void *arg, uint32_t id)
|
430
457
|
{
|
431
458
|
DesCtx *c;
|
@@ -11,6 +11,56 @@
|
|
11
11
|
#include <cstring>
|
12
12
|
#include <vector>
|
13
13
|
|
14
|
+
// note: the filter function gets called inside the safe context,
|
15
|
+
// i.e., the context that has not been tampered with by user JS
|
16
|
+
// convention: $-prefixed identifiers signify objects from the
|
17
|
+
// user JS context and should be handled with special care
|
18
|
+
static const char safe_context_script_source[] = R"js(
|
19
|
+
;(function($globalThis) {
|
20
|
+
const {Map: $Map, Set: $Set} = $globalThis
|
21
|
+
const sentinel = {}
|
22
|
+
return function filter(v) {
|
23
|
+
if (typeof v === "function")
|
24
|
+
return sentinel
|
25
|
+
if (typeof v !== "object" || v === null)
|
26
|
+
return v
|
27
|
+
if (v instanceof $Map) {
|
28
|
+
const m = new Map()
|
29
|
+
for (let [k, t] of Map.prototype.entries.call(v)) {
|
30
|
+
t = filter(t)
|
31
|
+
if (t !== sentinel)
|
32
|
+
m.set(k, t)
|
33
|
+
}
|
34
|
+
return m
|
35
|
+
} else if (v instanceof $Set) {
|
36
|
+
const s = new Set()
|
37
|
+
for (let t of Set.prototype.values.call(v)) {
|
38
|
+
t = filter(t)
|
39
|
+
if (t !== sentinel)
|
40
|
+
s.add(t)
|
41
|
+
}
|
42
|
+
return s
|
43
|
+
} else {
|
44
|
+
const o = Array.isArray(v) ? [] : {}
|
45
|
+
const pds = Object.getOwnPropertyDescriptors(v)
|
46
|
+
for (const [k, d] of Object.entries(pds)) {
|
47
|
+
if (!d.enumerable)
|
48
|
+
continue
|
49
|
+
let t = d.value
|
50
|
+
if (d.get) {
|
51
|
+
// *not* d.get.call(...), may have been tampered with
|
52
|
+
t = Function.prototype.call.call(d.get, v, k)
|
53
|
+
}
|
54
|
+
t = filter(t)
|
55
|
+
if (t !== sentinel)
|
56
|
+
Object.defineProperty(o, k, {value: t, enumerable: true})
|
57
|
+
}
|
58
|
+
return o
|
59
|
+
}
|
60
|
+
}
|
61
|
+
})
|
62
|
+
)js";
|
63
|
+
|
14
64
|
struct Callback
|
15
65
|
{
|
16
66
|
struct State *st;
|
@@ -32,8 +82,10 @@ struct State
|
|
32
82
|
// extra context for when we need access to built-ins like Array
|
33
83
|
// and want to be sure they haven't been tampered with by JS code
|
34
84
|
v8::Local<v8::Context> safe_context;
|
35
|
-
v8::
|
36
|
-
v8::Persistent<v8::Context>
|
85
|
+
v8::Local<v8::Function> safe_context_function;
|
86
|
+
v8::Persistent<v8::Context> persistent_context; // single-thread mode only
|
87
|
+
v8::Persistent<v8::Context> persistent_safe_context; // single-thread mode only
|
88
|
+
v8::Persistent<v8::Function> persistent_safe_context_function; // single-thread mode only
|
37
89
|
Context *ruby_context;
|
38
90
|
int64_t max_memory;
|
39
91
|
int err_reason;
|
@@ -73,6 +125,23 @@ struct Serialized
|
|
73
125
|
// throws JS exception on serialization error
|
74
126
|
bool reply(State& st, v8::Local<v8::Value> v)
|
75
127
|
{
|
128
|
+
v8::TryCatch try_catch(st.isolate);
|
129
|
+
{
|
130
|
+
Serialized serialized(st, v);
|
131
|
+
if (serialized.data) {
|
132
|
+
v8_reply(st.ruby_context, serialized.data, serialized.size);
|
133
|
+
return true;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
if (!try_catch.CanContinue()) {
|
137
|
+
try_catch.ReThrow();
|
138
|
+
return false;
|
139
|
+
}
|
140
|
+
auto recv = v8::Undefined(st.isolate);
|
141
|
+
if (!st.safe_context_function->Call(st.safe_context, recv, 1, &v).ToLocal(&v)) {
|
142
|
+
try_catch.ReThrow();
|
143
|
+
return false;
|
144
|
+
}
|
76
145
|
Serialized serialized(st, v);
|
77
146
|
if (serialized.data)
|
78
147
|
v8_reply(st.ruby_context, serialized.data, serialized.size);
|
@@ -240,7 +309,29 @@ extern "C" State *v8_thread_init(Context *c, const uint8_t *snapshot_buf,
|
|
240
309
|
st.safe_context = v8::Context::New(st.isolate);
|
241
310
|
st.context = v8::Context::New(st.isolate);
|
242
311
|
v8::Context::Scope context_scope(st.context);
|
312
|
+
{
|
313
|
+
v8::Context::Scope context_scope(st.safe_context);
|
314
|
+
auto source = v8::String::NewFromUtf8Literal(st.isolate, safe_context_script_source);
|
315
|
+
auto filename = v8::String::NewFromUtf8Literal(st.isolate, "safe_context_script.js");
|
316
|
+
v8::ScriptOrigin origin(filename);
|
317
|
+
auto script =
|
318
|
+
v8::Script::Compile(st.safe_context, source, &origin)
|
319
|
+
.ToLocalChecked();
|
320
|
+
auto function_v = script->Run(st.safe_context).ToLocalChecked();
|
321
|
+
auto function = v8::Function::Cast(*function_v);
|
322
|
+
auto recv = v8::Undefined(st.isolate);
|
323
|
+
v8::Local<v8::Value> arg = st.context->Global();
|
324
|
+
// grant the safe context access to the user context's globalThis
|
325
|
+
st.safe_context->SetSecurityToken(st.context->GetSecurityToken());
|
326
|
+
function_v =
|
327
|
+
function->Call(st.safe_context, recv, 1, &arg)
|
328
|
+
.ToLocalChecked();
|
329
|
+
// revoke access again now that the script did its one-time setup
|
330
|
+
st.safe_context->UseDefaultSecurityToken();
|
331
|
+
st.safe_context_function = v8::Local<v8::Function>::Cast(function_v);
|
332
|
+
}
|
243
333
|
if (single_threaded) {
|
334
|
+
st.persistent_safe_context_function.Reset(st.isolate, st.safe_context_function);
|
244
335
|
st.persistent_safe_context.Reset(st.isolate, st.safe_context);
|
245
336
|
st.persistent_context.Reset(st.isolate, st.context);
|
246
337
|
return pst; // intentionally returning early and keeping alive
|
@@ -792,12 +883,14 @@ extern "C" void v8_single_threaded_enter(State *pst, Context *c, void (*f)(Conte
|
|
792
883
|
v8::Isolate::Scope isolate_scope(st.isolate);
|
793
884
|
v8::HandleScope handle_scope(st.isolate);
|
794
885
|
{
|
886
|
+
st.safe_context_function = v8::Local<v8::Function>::New(st.isolate, st.persistent_safe_context_function);
|
795
887
|
st.safe_context = v8::Local<v8::Context>::New(st.isolate, st.persistent_safe_context);
|
796
888
|
st.context = v8::Local<v8::Context>::New(st.isolate, st.persistent_context);
|
797
889
|
v8::Context::Scope context_scope(st.context);
|
798
890
|
f(c);
|
799
891
|
st.context = v8::Local<v8::Context>();
|
800
892
|
st.safe_context = v8::Local<v8::Context>();
|
893
|
+
st.safe_context_function = v8::Local<v8::Function>();
|
801
894
|
}
|
802
895
|
}
|
803
896
|
|
@@ -31,6 +31,8 @@ static void des_named_props_begin(void *arg);
|
|
31
31
|
static void des_named_props_end(void *arg);
|
32
32
|
static void des_object_begin(void *arg);
|
33
33
|
static void des_object_end(void *arg);
|
34
|
+
static void des_map_begin(void *arg);
|
35
|
+
static void des_map_end(void *arg);
|
34
36
|
static void des_object_ref(void *arg, uint32_t id);
|
35
37
|
// des_error_begin: followed by des_object_begin + des_object_end calls
|
36
38
|
static void des_error_begin(void *arg);
|
@@ -642,7 +644,7 @@ again:
|
|
642
644
|
des_object_end(arg);
|
643
645
|
break;
|
644
646
|
case ';': // Map
|
645
|
-
|
647
|
+
des_map_begin(arg);
|
646
648
|
for (u = 0; /*empty*/; u++) {
|
647
649
|
if (*p >= pe)
|
648
650
|
goto too_short;
|
@@ -658,7 +660,7 @@ again:
|
|
658
660
|
goto bad_varint;
|
659
661
|
if (t != 2*u)
|
660
662
|
return bail(err, "map element count mismatch");
|
661
|
-
|
663
|
+
des_map_end(arg);
|
662
664
|
break;
|
663
665
|
case '\'': // Set
|
664
666
|
des_array_begin(arg);
|
data/lib/mini_racer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_racer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.17.0.
|
4
|
+
version: 0.17.0.pre11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-01-
|
11
|
+
date: 2025-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -123,9 +123,9 @@ licenses:
|
|
123
123
|
- MIT
|
124
124
|
metadata:
|
125
125
|
bug_tracker_uri: https://github.com/discourse/mini_racer/issues
|
126
|
-
changelog_uri: https://github.com/discourse/mini_racer/blob/v0.17.0.
|
127
|
-
documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.17.0.
|
128
|
-
source_code_uri: https://github.com/discourse/mini_racer/tree/v0.17.0.
|
126
|
+
changelog_uri: https://github.com/discourse/mini_racer/blob/v0.17.0.pre11/CHANGELOG
|
127
|
+
documentation_uri: https://www.rubydoc.info/gems/mini_racer/0.17.0.pre11
|
128
|
+
source_code_uri: https://github.com/discourse/mini_racer/tree/v0.17.0.pre11
|
129
129
|
post_install_message:
|
130
130
|
rdoc_options: []
|
131
131
|
require_paths:
|