Skip to content

Commit d4ad5ba

Browse files
author
Ralph Küpper
committed
address CodeRabbit review (#5606)
- js_object_has_property: narrow the handle-band crash guard to the fetch/zlib bands (>= COMMON_HANDLE_BAND_END). Common/small handles now fall through to the registered small-handle property path instead of always returning false. - headers_init_json_ptr: normalize null/undefined headers to {} in the shared helper so the codegen js_fetch_headers_to_json path matches the runtime thunk (previously serialized headers:null as "null").
1 parent 1da9cbc commit d4ad5ba

2 files changed

Lines changed: 28 additions & 19 deletions

File tree

crates/perry-runtime/src/object/field_get_set.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,17 +2263,21 @@ pub extern "C" fn js_object_has_property(obj: f64, key: f64) -> f64 {
22632263
};
22642264
}
22652265

2266-
// A handle-band value (Web Fetch Headers/Request/Response, net/http handles,
2267-
// zlib streams) is a registry id, not a heap object — the pointer paths below
2268-
// would dereference the id and segfault. `key in <handle>` has no own-property
2269-
// meaning for these registry handles, so report `false` instead of crashing.
2270-
// Same handle-band family as the string_from_header / inline-`.length` guards.
2271-
if obj_val.is_pointer()
2272-
&& crate::value::addr_class::is_handle_band(
2273-
(obj_val.bits() & crate::value::POINTER_MASK) as usize,
2274-
)
2275-
{
2276-
return nanbox_false;
2266+
// A Web Fetch / zlib handle-band value (Headers/Request/Response, zlib
2267+
// streams) at or above the fetch band is a registry id, not a heap object —
2268+
// the pointer paths below would dereference the id and segfault. `key in
2269+
// <handle>` has no own-property meaning for these, so report `false`.
2270+
// Common/small handles (below the fetch band) are intentionally NOT caught
2271+
// here: they fall through to the registered small-handle property path later
2272+
// in this function. Same family as the string_from_header / inline-`.length`
2273+
// guards.
2274+
if obj_val.is_pointer() {
2275+
let addr = (obj_val.bits() & crate::value::POINTER_MASK) as usize;
2276+
if addr >= crate::value::addr_class::COMMON_HANDLE_BAND_END
2277+
&& crate::value::addr_class::is_handle_band(addr)
2278+
{
2279+
return nanbox_false;
2280+
}
22772281
}
22782282

22792283
// #1758: a SYMBOL key. The class-ref path below + the keys_array scan

crates/perry-runtime/src/object/global_fetch.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,9 @@ pub extern "C" fn js_fetch_headers_to_json(headers: f64) -> i64 {
160160

161161
fn fetch_headers_json_ptr(init: f64) -> *const crate::StringHeader {
162162
let headers = fetch_option(init, b"headers");
163-
if matches!(
164-
headers.to_bits(),
165-
crate::value::TAG_UNDEFINED | crate::value::TAG_NULL
166-
) {
167-
return crate::string::js_string_from_bytes(b"{}".as_ptr(), 2);
168-
}
169-
// `init.headers` may be a `Headers` instance (a fetch-band handle) rather
170-
// than a plain object — JSON-stringify it without dereferencing the handle.
163+
// `init.headers` may be a `Headers` instance (a fetch-band handle), a plain
164+
// object, or null/undefined — `headers_init_json_ptr` normalizes all three
165+
// (Headers handle read from its registry, null/undefined → `{}`).
171166
headers_init_json_ptr(headers)
172167
}
173168

@@ -301,6 +296,16 @@ fn call_global_headers_object_json(value: f64) -> *mut crate::StringHeader {
301296
/// safely. Same family as #5559/#5560 (handle-band ids mis-dereferenced as heap
302297
/// pointers).
303298
fn headers_init_json_ptr(headers: f64) -> *const crate::StringHeader {
299+
// Normalize null/undefined to an empty object so BOTH entry points — the
300+
// codegen `js_fetch_headers_to_json` and the runtime `fetch_headers_json_ptr`
301+
// — serialize `headers: null` as `{}` rather than the literal `"null"` that
302+
// `js_fetch_with_options` cannot parse.
303+
if matches!(
304+
headers.to_bits(),
305+
crate::value::TAG_UNDEFINED | crate::value::TAG_NULL
306+
) {
307+
return crate::string::js_string_from_bytes(b"{}".as_ptr(), 2);
308+
}
304309
let jsv = crate::value::JSValue::from_bits(headers.to_bits());
305310
if jsv.is_pointer() {
306311
let addr = (headers.to_bits() & 0x0000_FFFF_FFFF_FFFF) as usize;

0 commit comments

Comments
 (0)