Skip to content

Commit 32db3d1

Browse files
mikolalysenkoclaude
andcommitted
Match the bun spec before the bundled parse in vendor, with a fast path
classify_rewritable and bundled_matches now run classify first and only parse the meta of entries that match the target. is_bundled_entry skips the JSON parse when the meta never spells "bundled" and holds no backslash (so an escaped key still takes the parse). Malformed meta that mentions "bundled" still fails closed. Refs #578, #580 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 4fa38e4 commit 32db3d1

2 files changed

Lines changed: 31 additions & 5 deletions

File tree

‎crates/socket-patch-core/src/vendor/bun_lock.rs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,10 +1092,10 @@ fn classify_rewritable(
10921092
name: &str,
10931093
target_leaf: &str,
10941094
) -> Option<TupleShape> {
1095-
if is_bundled_entry(entry) {
1096-
return None;
1097-
}
1098-
classify(entry, target_spec, name, target_leaf)
1095+
// The cheap spec match runs first; the bundled parse only for a match
1096+
// (#580).
1097+
let shape = classify(entry, target_spec, name, target_leaf)?;
1098+
(!is_bundled_entry(entry)).then_some(shape)
10991099
}
11001100

11011101
/// Keys of the bundled entries that resolve the target `name@version`.
@@ -1107,7 +1107,7 @@ fn bundled_matches(
11071107
) -> Vec<String> {
11081108
entries
11091109
.iter()
1110-
.filter(|e| is_bundled_entry(e) && classify(e, target_spec, name, target_leaf).is_some())
1110+
.filter(|e| classify(e, target_spec, name, target_leaf).is_some() && is_bundled_entry(e))
11111111
.map(|e| e.key.clone())
11121112
.collect()
11131113
}

‎crates/socket-patch-core/src/vendor/bun_lock_text.rs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ pub(crate) fn is_bundled_entry(entry: &BunEntry) -> bool {
229229
let Some(meta) = entry.elems.iter().skip(1).find(|e| e.starts_with('{')) else {
230230
return false;
231231
};
232+
// Fast path (#580): a meta that never spells `bundled` cannot carry the
233+
// key. A backslash could hide it behind a JSON escape, so only a meta
234+
// with neither skips the parse.
235+
if !meta.contains("bundled") && !meta.contains('\\') {
236+
return false;
237+
}
232238
match serde_json::from_str::<serde_json::Value>(meta) {
233239
Ok(value) => value.get("bundled").and_then(serde_json::Value::as_bool) == Some(true),
234240
Err(_) => meta.contains("\"bundled\""),
@@ -717,6 +723,26 @@ mod tests {
717723
));
718724
}
719725

726+
/// The substring fast path (#580) never changes the answer: a meta that
727+
/// never spells `bundled` is not bundled, a malformed meta that does
728+
/// still fails closed, and a JSON-escaped key still takes the parse.
729+
#[test]
730+
fn bundled_fast_path_matches_the_full_parse() {
731+
let bundled = |line: &str| is_bundled_entry(&parse_entry_line(line).unwrap());
732+
assert!(!bundled(
733+
r#" "q": ["q@1.0.0", "", { "dependencies": { "a": "1" } }, "sha512-X=="],"#
734+
));
735+
assert!(!bundled(
736+
r#" "q": ["q@1.0.0", "", { "x": , }, "sha512-X=="],"#
737+
));
738+
assert!(bundled(
739+
r#" "q": ["q@1.0.0", "", { "bundled": true, "x": , }, "sha512-X=="],"#
740+
));
741+
assert!(bundled(
742+
r#" "q": ["q@1.0.0", "", { "bundl\u0065d": true }, "sha512-X=="],"#
743+
));
744+
}
745+
720746
#[test]
721747
fn line_grammar_parses_the_fixture_shapes() {
722748
// Registry 4-tuple with deps and trailing comma.

0 commit comments

Comments
 (0)