mini_racer 0.17.0.pre9 → 0.17.0.pre11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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:
|