#!/usr/bin/env python3 -I """Minimal-extraction items (Phase 5 Part A, "extract the affected pure function into a minimal standalone crate"). Each KERNEL is a hand-extracted, dependency-free reduction of the *decision logic* that a RustSec fix changed (pre = vulnerable revision's logic, post = patched revision's logic). Whole crates are not translatable (native deps, dyn traits, early returns in loops, ...: see TOOLCHAIN.md / SUMMARY.json), so the unit is the function kernel. `fidelity`: verbatim_logic the changed expression/branch is copied from the crate with std/crate types replaced by integers/slices model_of_std the vulnerable behaviour lives in a std/crate call (slice split_at, str slicing, unchecked memcpy length); the kernel models that call's panic/UB condition explicitly. Weaker; reported separately. Extraction was done by reading the pre/post diff, so kernels are NOT blind to the bug; only the *properties* (property bank) are authored blind, from `spec_doc` + signature alone (see baselines/bank/README_PROVENANCE.md). Writes bench/kernels//{meta.json,pre/{Cargo.toml,src/lib.rs},post/{Cargo.toml,src/lib.rs}}. """ import json, os HERE = os.path.dirname(os.path.abspath(__file__)) CAND = "/apps/development/rlhf/bugfind_data/out/advisory_candidates.jsonl" K = [] def k(kid, adv, fn, sig, spec_doc, bug_class, fidelity, pre, post, witness, note, file): K.append(dict(id=kid, adv=adv, fn=fn, sig=sig, spec_doc=spec_doc, bug_class=bug_class, fidelity=fidelity, pre=pre.strip() + "\n", post=post.strip() + "\n", witness=witness, note=note, file=file)) k("claxon_rice", "RUSTSEC-2018-0004", "rice_layout", "pub fn rice_layout(block_size: u16, order: u32, n_warm_up: u16) -> Result", "Computes how many residual samples a FLAC Rice-coded subframe's 2^order partitions cover (order is a 4-bit field, so order > 15 is rejected with Err). On Ok(n), n must equal block_size (the partitions fill the block); otherwise return Err.", "logic", "verbatim_logic", """ pub fn rice_layout(block_size: u16, order: u32, n_warm_up: u16) -> Result { if order > 15 { return Err(3); } let n_partitions = 1u32 << order; let n_samples_per_partition = block_size >> order; if n_warm_up > n_samples_per_partition { return Err(1); } Ok(n_partitions * (n_samples_per_partition as u32)) } """, """ pub fn rice_layout(block_size: u16, order: u32, n_warm_up: u16) -> Result { if order > 15 { return Err(3); } let n_partitions = 1u32 << order; let n_samples_per_partition = block_size >> order; if block_size & ((n_partitions - 1) as u16) != 0 { return Err(2); } if n_warm_up > n_samples_per_partition { return Err(1); } Ok(n_partitions * (n_samples_per_partition as u32)) } """, "10u16, 2u32, 0u16", "src/subframe.rs decode_residual: block size not a multiple of 2^order left buffer tail uninitialised", "src/subframe.rs") k("bytes_reserve", "RUSTSEC-2026-0007", "reserve_fits", "pub fn reserve_fits(v_capacity: usize, new_cap: usize, offset: usize) -> bool", "Decides whether a Vec-backed buffer with capacity v_capacity can serve a reserve request of new_cap bytes when the live window starts at offset; must be true iff v_capacity >= new_cap + offset in exact arithmetic.", "overflow", "verbatim_logic", "pub fn reserve_fits(v_capacity: usize, new_cap: usize, offset: usize) -> bool {\n v_capacity >= new_cap + offset\n}", """ pub fn reserve_fits(v_capacity: usize, new_cap: usize, offset: usize) -> bool { match new_cap.checked_add(offset) { Some(s) => v_capacity >= s, None => false, } } """, "10usize, usize::MAX, 1usize", "src/bytes_mut.rs reserve_inner: new_cap + offset overflow", "src/bytes_mut.rs") k("mldsa_hint", "RUSTSEC-2026-0076", "hint_weight", "pub fn hint_weight(hint: &[u8], max_ones: usize, rows: usize) -> Option", "Decodes the ML-DSA signature hint encoding: hint[..max_ones] are positions, hint[max_ones..max_ones+rows] are cumulative counts that must be non-decreasing and at most max_ones. Returns the sum of the hint bytes it consumed, or None for a malformed encoding. Must never panic on any input of length >= max_ones+rows.", "panic", "verbatim_logic", """ pub fn hint_weight(hint: &[u8], max_ones: usize, rows: usize) -> Option { let mut previous = 0usize; let mut total = 0usize; let mut bad = false; let mut i = 0usize; while i < rows { let current = hint[max_ones + i] as usize; if current < previous || previous > max_ones { bad = true; } else { let mut j = previous; while j < current { total += hint[j] as usize; j += 1; } previous = current; } i += 1; } if bad { None } else { Some(total) } } """, """ pub fn hint_weight(hint: &[u8], max_ones: usize, rows: usize) -> Option { let mut previous = 0usize; let mut total = 0usize; let mut bad = false; let mut i = 0usize; while i < rows { let current = hint[max_ones + i] as usize; if current < previous || current > max_ones { bad = true; } else { let mut j = previous; while j < current { total += hint[j] as usize; j += 1; } previous = current; } i += 1; } if bad { None } else { Some(total) } } """, "&[0u8, 0, 200], 2usize, 1usize", "src/ml_dsa_generic.rs / encoding/signature.rs deserialize hint: checked previous instead of current against max_ones", "src/encoding/signature.rs") k("mldsa_norm", "RUSTSEC-2026-0076", "response_bound", "pub fn response_bound(gamma1_exponent: u32, beta: i32) -> i32", "ML-DSA verification bound for the signer response: gamma1 - beta where gamma1 = 2^gamma1_exponent.", "logic", "verbatim_logic", "pub fn response_bound(gamma1_exponent: u32, beta: i32) -> i32 {\n (2i32 << gamma1_exponent) - beta\n}", "pub fn response_bound(gamma1_exponent: u32, beta: i32) -> i32 {\n (1i32 << gamma1_exponent) - beta\n}", "17u32, 78i32", "src/ml_dsa_generic.rs verify: (2 << GAMMA1_EXPONENT) - BETA instead of (1 << ...) - BETA", "src/ml_dsa_generic.rs") k("odoh_split", "RUSTSEC-2023-0095", "encrypted_payload_len", "pub fn encrypted_payload_len(msg: &[u8], key_size: usize) -> Result", "Splits an encrypted ODoH query into an encapsulated key (first key_size bytes) and ciphertext (the rest); returns the ciphertext length, or Err if the message is shorter than key_size. Must not panic on any input.", "panic", "model_of_std", "pub fn encrypted_payload_len(msg: &[u8], key_size: usize) -> Result {\n let ct = &msg[key_size..];\n Ok(ct.len())\n}", "pub fn encrypted_payload_len(msg: &[u8], key_size: usize) -> Result {\n if key_size > msg.len() {\n return Err(1);\n }\n let ct = &msg[key_size..];\n Ok(ct.len())\n}", "&[1u8, 2, 3], 32usize", "src/protocol.rs decrypt_query: split_at(key_size) without length check", "src/protocol.rs") k("matrix_power", "RUSTSEC-2025-0065", "normalize_power_level", "pub fn normalize_power_level(power_level: i64, max_power_level: i64) -> i64", "Scales a Matrix user power level (|power_level| < 2^53) to the range 0..=100 relative to max_power_level > 0.", "panic", "verbatim_logic", """ const INT_MAX: i64 = 9007199254740991; pub fn normalize_power_level(power_level: i64, max_power_level: i64) -> i64 { let n = (power_level * 100) / max_power_level; assert!(n >= -INT_MAX && n <= INT_MAX); n } """, """ pub fn normalize_power_level(power_level: i64, max_power_level: i64) -> i64 { let n = (power_level * 100) / max_power_level; if n < 0 { 0 } else if n > 100 { 100 } else { n } } """, "9007199254740991i64, 1i64", "src/room/members.rs normalized_power_level: expect() on out-of-range Int when max_power_level is small", "src/room/members.rs") k("nostr_iv", "RUSTSEC-2026-0219", "load_iv", "pub fn load_iv(iv: &[u8]) -> Result<[u8; 16], u8>", "Loads a NIP-04 AES-CBC initialisation vector from untrusted bytes; must return Err unless the input is exactly 16 bytes, and must never panic.", "panic", "model_of_std", """ pub fn load_iv(iv: &[u8]) -> Result<[u8; 16], u8> { let mut out = [0u8; 16]; let mut i = 0usize; while i < 16 { out[i] = iv[i]; i += 1; } Ok(out) } """, """ pub fn load_iv(iv: &[u8]) -> Result<[u8; 16], u8> { if iv.len() != 16 { return Err(1); } let mut out = [0u8; 16]; let mut i = 0usize; while i < 16 { out[i] = iv[i]; i += 1; } Ok(out) } """, "&[1u8, 2, 3]", "src/nips/nip04.rs decrypt: iv.as_slice().into() panics on wrong length", "src/nips/nip04.rs") k("phone_ctx", "RUSTSEC-2023-0082", "context_prefix_skip", "pub fn context_prefix_skip(s: &[u8]) -> usize", "Returns how many leading bytes of an RFC3966 phone-context value to skip: 1 if it starts with '+', otherwise 0. Must not panic on empty input.", "panic", "verbatim_logic", "pub fn context_prefix_skip(s: &[u8]) -> usize {\n if s[0] == b'+' { 1 } else { 0 }\n}", "pub fn context_prefix_skip(s: &[u8]) -> usize {\n if !s.is_empty() && s[0] == b'+' { 1 } else { 0 }\n}", "&[]", "src/parser/rfc3966.rs: s.as_bytes()[0] on empty phone-context", "src/parser/rfc3966.rs") k("poly1305_key", "RUSTSEC-2026-0073", "key_len_ok", "pub fn key_len_ok(key: &[u8]) -> bool", "Poly1305 one-time keys are r (16 bytes) followed by s (16 bytes): a key is acceptable iff it is exactly 32 bytes.", "logic", "verbatim_logic", "pub const KEY_LEN: usize = 16;\npub fn key_len_ok(key: &[u8]) -> bool {\n key.len() == KEY_LEN\n}", "pub const KEY_LEN: usize = 32;\npub fn key_len_ok(key: &[u8]) -> bool {\n key.len() == KEY_LEN\n}", "&[0u8; 32]", "src/lib.rs KEY_LEN = 16 (standalone mac rejected/panicked on real 32-byte keys)", "src/lib.rs") k("ecdh_scalar", "RUSTSEC-2026-0023", "validate_x25519_scalar", "pub fn validate_x25519_scalar(s: &[u8]) -> bool", "Validates an X25519 secret scalar: must be exactly 32 bytes, not all zero, and clamped (low 3 bits of byte 0 clear, top bit of byte 31 clear, second-highest bit of byte 31 set).", "logic", "verbatim_logic", """ pub fn validate_x25519_scalar(s: &[u8]) -> bool { let mut all_zero = true; let mut i = 0usize; while i < s.len() { if s[i] != 0 { all_zero = false; } i += 1; } !all_zero } """, """ pub fn validate_x25519_scalar(s: &[u8]) -> bool { if s.len() != 32 { return false; } let mut all_zero = true; let mut i = 0usize; while i < s.len() { if s[i] != 0 { all_zero = false; } i += 1; } if all_zero { return false; } (s[0] & 7) == 0 && (s[31] & 128) == 0 && (s[31] & 64) != 0 } """, "&[1u8, 2, 3]", "src/ecdh.rs validate_scalar: only checked all-zero", "src/ecdh.rs") k("nanoid_mask", "RUSTSEC-2024-0343", "alphabet_mask", "pub fn alphabet_mask(len: usize) -> usize", "Bit mask used to index an alphabet of len symbols (len >= 2) from a random byte: the smallest all-ones value m with m >= len - 1, i.e. next_power_of_two(len) - 1.", "logic", "verbatim_logic", "pub fn alphabet_mask(len: usize) -> usize {\n len - 1\n}", """ pub fn alphabet_mask(len: usize) -> usize { let mut p = 1usize; while p < len { p = p * 2; } p - 1 } """, "62usize", "src/lib.rs MASK = $len - 1 is not a bit mask for non-power-of-two alphabets (biased/short alphabet)", "src/lib.rs") k("tar_pax", "RUSTSEC-2026-0145", "apply_pax", "pub fn apply_pax(entry_type: u8, has_pax: bool) -> bool", "PAX extended-header data describes the next file entry. Returns whether pending PAX data must be applied to a header of the given type byte: only for real entries, never for GNU long-name 'L', long-link 'K', PAX local 'x' or global 'g' headers.", "logic", "verbatim_logic", "pub fn apply_pax(entry_type: u8, has_pax: bool) -> bool {\n has_pax\n}", """ pub fn apply_pax(entry_type: u8, has_pax: bool) -> bool { let mut is_extension_header = false; if entry_type == b'L' || entry_type == b'K' || entry_type == b'x' || entry_type == b'g' { is_extension_header = true; } if has_pax { if is_extension_header { false } else { true } } else { false } } """, "b'L', true", "src/archive.rs: PAX data applied to extension headers (desynchronisation)", "src/archive.rs") k("exif_discard", "RUSTSEC-2021-0143", "discard_exact", "pub fn discard_exact(avail: usize, len: usize) -> Result", "Models skipping len bytes of a reader that has only avail bytes: returns Ok(number of read rounds) when the reader had enough data, Err when it hits EOF early. Must terminate on every input.", "dos_loop_or_recursion", "verbatim_logic", """ pub fn discard_exact(avail: usize, len: usize) -> Result { let mut avail = avail; let mut len = len; let mut rounds = 0usize; while len > 0 { let consume_len = if avail < len { avail } else { len }; avail -= consume_len; len -= consume_len; rounds += 1; } Ok(rounds) } """, """ pub fn discard_exact(avail: usize, len: usize) -> Result { let mut avail = avail; let mut len = len; let mut rounds = 0usize; let mut eof = false; while len > 0 && !eof { let consume_len = if avail < len { avail } else { len }; if consume_len == 0 { eof = true; } else { avail -= consume_len; len -= consume_len; rounds += 1; } } if eof { Err(1) } else { Ok(rounds) } } """, "3usize, 10usize", "src/util.rs discard_exact: spins forever at EOF (consume_len == 0)", "src/util.rs") k("trustdns_ptr", "RUSTSEC-2018-0007", "pointer_ok", "pub fn pointer_ok(location: usize, pointer_location: usize, name_start: usize) -> bool", "A DNS name-compression pointer is acceptable iff its target lies strictly before the start of the name currently being parsed (so pointer chains cannot loop).", "dos_loop_or_recursion", "verbatim_logic", "pub fn pointer_ok(location: usize, pointer_location: usize, name_start: usize) -> bool {\n let _ = name_start;\n location < pointer_location\n}", "pub fn pointer_ok(location: usize, pointer_location: usize, name_start: usize) -> bool {\n let _ = pointer_location;\n location < name_start\n}", "0usize, 2usize, 0usize", "src/rr/domain/name.rs Name::read: pointer compared with current label instead of name start (self-referential name)", "src/rr/domain/name.rs") k("ring_ctr", "RUSTSEC-2025-0009", "increment_by", "pub fn increment_by(old_value: u32, increment_by: u32) -> u32", "Increments a 32-bit big-endian AES-GCM block counter, wrapping modulo 2^32.", "overflow", "verbatim_logic", "pub fn increment_by(old_value: u32, increment_by: u32) -> u32 {\n old_value + increment_by\n}", "pub fn increment_by(old_value: u32, increment_by: u32) -> u32 {\n old_value.wrapping_add(increment_by)\n}", "4294967295u32, 1u32", "src/aead/aes.rs increment_by_less_safe: + panics with overflow checks", "src/aead/aes.rs") k("stack_insert", "RUSTSEC-2020-0042", "insert_shift_len", "pub fn insert_shift_len(len: usize, index: usize) -> Result", "Number of elements to shift when inserting at index into a vector of length len; Err if index > len.", "panic", "model_of_std", "pub fn insert_shift_len(len: usize, index: usize) -> Result {\n Ok(len.wrapping_sub(index))\n}", "pub fn insert_shift_len(len: usize, index: usize) -> Result {\n if index > len {\n return Err(1);\n }\n Ok(len - index)\n}", "3usize, 5usize", "src/vector.rs insert: missing index <= len assert; copy length len - index wrapped (release) -> OOB write", "src/vector.rs") k("tract_len", "RUSTSEC-2026-0217", "tensor_len_ok", "pub fn tensor_len_ok(dims: &[usize], bits_per_item: usize, data_size_bytes: usize) -> bool", "NNEF tensor header consistency: true iff prod(dims) * (bits_per_item / 8) == data_size_bytes in exact arithmetic (false if the product does not fit usize).", "overflow", "verbatim_logic", """ pub fn tensor_len_ok(dims: &[usize], bits_per_item: usize, data_size_bytes: usize) -> bool { let mut len = 1usize; let mut i = 0usize; while i < dims.len() { len = len * dims[i]; i += 1; } len * (bits_per_item / 8) == data_size_bytes } """, """ pub fn tensor_len_ok(dims: &[usize], bits_per_item: usize, data_size_bytes: usize) -> bool { let mut len = 1usize; let mut overflow = false; let mut i = 0usize; while i < dims.len() { let d = dims[i]; if d != 0 && len > usize::MAX / d { overflow = true; } else { len = len * d; } i += 1; } if overflow { return false; } let per = bits_per_item / 8; if per != 0 && len > usize::MAX / per { return false; } len * per == data_size_bytes } """, "&[4294967296usize, 4294967296], 8usize, 0usize", "src/tensors.rs read_tensor: unchecked shape product", "src/tensors.rs") k("transpose_dims", "RUSTSEC-2023-0080", "dims_match", "pub fn dims_match(width: usize, height: usize, len: usize) -> bool", "True iff width * height == len in exact arithmetic (false when the product does not fit usize).", "overflow", "verbatim_logic", "pub fn dims_match(width: usize, height: usize, len: usize) -> bool {\n width * height == len\n}", "pub fn dims_match(width: usize, height: usize, len: usize) -> bool {\n match width.checked_mul(height) {\n Some(p) => p == len,\n None => false,\n }\n}", "4294967296usize, 4294967296usize, 0usize", "src/lib.rs transpose: assert_eq!(w*h, len) wraps in release -> buffer overflow", "src/lib.rs") k("toodee_drain", "RUSTSEC-2025-0062", "drain_col_copy_len", "pub fn drain_col_copy_len(orig_cols: usize, col: usize) -> usize", "When removing column col from a row of orig_cols cells, the number of cells to shift left: those strictly after col (orig_cols - col - 1).", "overflow", "verbatim_logic", "pub fn drain_col_copy_len(orig_cols: usize, col: usize) -> usize {\n orig_cols - col\n}", "pub fn drain_col_copy_len(orig_cols: usize, col: usize) -> usize {\n orig_cols - col - 1\n}", "5usize, 2usize", "src/toodee.rs DrainCol::drop: ptr::copy length off by one (heap overflow)", "src/toodee.rs") k("tinyhttp_hdr", "RUSTSEC-2020-0031", "header_field_ok", "pub fn header_field_ok(s: &[u8]) -> bool", "A header field name is valid iff it is ASCII and contains no whitespace (no trimming: ' Transfer-Encoding' and 'Transfer-Encoding ' are invalid).", "logic", "verbatim_logic", """ fn is_ws(b: u8) -> bool { b == b' ' || b == b'\\t' || b == b'\\n' || b == b'\\r' || b == 11u8 || b == 12u8 } pub fn header_field_ok(s: &[u8]) -> bool { let mut start = 0usize; let mut end = s.len(); while start < end && is_ws(s[start]) { start += 1; } while end > start && is_ws(s[end - 1]) { end -= 1; } let mut ok = true; let mut i = start; while i < end { if s[i] >= 128 { ok = false; } i += 1; } ok } """, """ fn is_ws(b: u8) -> bool { b == b' ' || b == b'\\t' || b == b'\\n' || b == b'\\r' || b == 11u8 || b == 12u8 } pub fn header_field_ok(s: &[u8]) -> bool { let mut ok = true; let mut i = 0usize; while i < s.len() { if s[i] >= 128 || is_ws(s[i]) { ok = false; } i += 1; } ok } """, "b\"Transfer-Encoding \"", "src/common.rs HeaderField::from_str: trimmed whitespace (request smuggling)", "src/common.rs") k("evm_memset", "RUSTSEC-2021-0066", "memory_set_len", "pub fn memory_set_len(cur_len: usize, offset: usize, value_len: usize, target_size: Option, limit: usize) -> Result", "New length of EVM memory after writing value (value_len bytes) at offset, zero-padded to target_size (default value_len). Err if offset+target_size exceeds limit. Writing an empty value must not grow memory.", "dos_loop_or_recursion", "verbatim_logic", """ pub fn memory_set_len(cur_len: usize, offset: usize, value_len: usize, target_size: Option, limit: usize) -> Result { let target = match target_size { Some(t) => t, None => value_len, }; match offset.checked_add(target) { Some(pos) => { if pos > limit { return Err(1); } } None => return Err(1), } if cur_len < offset + target { Ok(offset + target) } else { Ok(cur_len) } } """, """ pub fn memory_set_len(cur_len: usize, offset: usize, value_len: usize, target_size: Option, limit: usize) -> Result { if value_len == 0 { return Ok(cur_len); } let target = match target_size { Some(t) => t, None => value_len, }; match offset.checked_add(target) { Some(pos) => { if pos > limit { return Err(1); } } None => return Err(1), } if cur_len < offset + target { Ok(offset + target) } else { Ok(cur_len) } } """, "0usize, 0usize, 0usize, Some(1000usize), 1048576usize", "src/memory.rs Memory::set: empty value with large target_size over-allocates", "src/memory.rs") k("bcrypt_split", "RUSTSEC-2026-0199", "split_hash_salt_len", "pub fn split_hash_salt_len(hash: &[u8]) -> Result", "Validates a bcrypt hash string and returns the salt length (22). A valid hash is exactly 60 ASCII bytes; every other input must give Err, never panic.", "panic", "model_of_std", """ fn is_char_boundary(b: u8) -> bool { b < 128 || b >= 192 } pub fn split_hash_salt_len(hash: &[u8]) -> Result { if hash.len() != 60 { return Err(1); } assert!(is_char_boundary(hash[22])); Ok(22) } """, """ pub fn split_hash_salt_len(hash: &[u8]) -> Result { if hash.len() != 60 { return Err(1); } let mut ascii = true; let mut i = 0usize; while i < hash.len() { if hash[i] >= 128 { ascii = false; } i += 1; } if !ascii { return Err(2); } Ok(22) } """, "&[b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', 0xA3, b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a']", "src/lib.rs split_hash: &str slicing at a non-char-boundary on non-ASCII 60-byte input", "src/lib.rs") k("versionize_fam", "RUSTSEC-2023-0030", "fam_entry", "pub fn fam_entry(entries: &[u32], header_len: usize, i: usize) -> Result", "Reads entry i (< header_len) of a deserialised flexible-array struct whose header declares header_len entries; Err if the header length disagrees with the actual number of entries, never panic.", "panic", "model_of_std", "pub fn fam_entry(entries: &[u32], header_len: usize, i: usize) -> Result {\n if i < header_len {\n Ok(entries[i])\n } else {\n Err(2)\n }\n}", "pub fn fam_entry(entries: &[u32], header_len: usize, i: usize) -> Result {\n if header_len != entries.len() {\n return Err(1);\n }\n if i < header_len {\n Ok(entries[i])\n } else {\n Err(2)\n }\n}", "&[7u32, 8], 5usize, 3usize", "src/primitives.rs FamStructWrapper::deserialize: header length not checked against entries", "src/primitives.rs") def main(): cand = {} for l in open(CAND): r = json.loads(l); cand[r["adv_id"]] = r root = os.path.join(HERE, "kernels") for e in K: c = cand[e["adv"]] d = os.path.join(root, e["id"]) for ver in ("pre", "post"): os.makedirs(f"{d}/{ver}/src", exist_ok=True) open(f"{d}/{ver}/Cargo.toml", "w").write(f'[package]\nname = "k_{e["id"]}_{ver}"\nversion = "0.1.0"\nedition = "2021"\n\n[lib]\npath = "src/lib.rs"\n\n[workspace]\n') open(f"{d}/{ver}/src/lib.rs", "w").write(e[ver]) meta = dict(item_id=f"ker-{e['id']}", kernel=e["id"], advisory=e["adv"], crate=c["crate"], pre_version=c["pre_version"], post_version=c["post_version"], advisory_url=c["url"], title=c["title"], source_file=e["file"], function=e["fn"], signature=e["sig"], spec_doc=e["spec_doc"], bug_class=e["bug_class"], fidelity=e["fidelity"], extraction_note=e["note"], witness_args=e["witness"], labels={"buggy": f"{c['crate']}@{c['pre_version']}", "reference": f"{c['crate']}@{c['post_version']}"}) json.dump(meta, open(f"{d}/meta.json", "w"), indent=1) print(len(K), "kernels written to", root) if __name__ == "__main__": main()