@@ -220,6 +220,60 @@ test_crlf_tolerated() {
220220 echo " PASS: CRLF tolerated"
221221}
222222
223+ # --- extract_key bash double-quote grammar edge cases ---
224+
225+ test_extract_key_preserves_literal_backslash () {
226+ # File contains the literal text: USER="abc\xyz"
227+ # Bash double-quote: \x is NOT in the escape set ({\, ", $, `}), so
228+ # the sourced value is the 7-byte literal abc\xyz. extract_key must
229+ # preserve the backslash and round-trip it through emit so sourcing
230+ # the migrated file yields the same value.
231+ local f
232+ f=" $( with_file " case_extract_backslash_literal" ' USER="abc\xyz"
233+ ' ) "
234+ run_migrator " $f "
235+ local got
236+ got=" $(
237+ # shellcheck source=/dev/null
238+ . " $f " && printf ' %s' " $MLAT_USER "
239+ ) " || fail " sourcing migrated file failed: $( cat " $f " ) "
240+ assert_eq ' abc\xyz' " $got " " literal backslash preserved in MLAT_USER"
241+ echo " PASS: extract_key preserves literal backslash for \\ X non-escape"
242+ }
243+
244+ test_extract_key_resolves_recognized_escapes () {
245+ # File contains: USER="a\\b\$c" (8 bytes between quotes)
246+ # Bash double-quote: \\ → \, \$ → $. Sourced value: a\b$c.
247+ local f
248+ f=" $( with_file " case_extract_escapes" ' USER="a\\b\$c"
249+ ' ) "
250+ run_migrator " $f "
251+ local got
252+ got=" $(
253+ # shellcheck source=/dev/null
254+ . " $f " && printf ' %s' " $MLAT_USER "
255+ ) " || fail " sourcing migrated file failed: $( cat " $f " ) "
256+ assert_eq ' a\b$c' " $got " " recognized backslash escapes resolved"
257+ echo " PASS: extract_key resolves recognized escapes (\\\\ , \\\$ )"
258+ }
259+
260+ test_extract_key_escaped_close_quote_no_real_close () {
261+ # File contains: USER="abc\" with newline after the escaped quote.
262+ # The trailing \" is the escape for a literal " (still inside the
263+ # string), so there is no real close-quote on this line. extract_key
264+ # must reject as malformed and leave the file untouched.
265+ local f rc=0
266+ f=" $( with_file " case_extract_escaped_close" ' USER="abc\"
267+ DUMP1090=yes
268+ ' ) "
269+ local before
270+ before=" $( cat " $f " ) "
271+ run_migrator " $f " 2> /dev/null || rc=$?
272+ [[ " $rc " -ne 0 ]] || fail " escaped close-quote not rejected"
273+ assert_file_eq " $before " " $f " " malformed file unchanged"
274+ echo " PASS: extract_key rejects escaped close-quote (no real close)"
275+ }
276+
223277# --- MLAT_MARKER → MLAT_PRIVATE migration (co-emit, MLAT_MARKER preserved) ---
224278
225279test_marker_no_emits_private_true_alongside () {
@@ -443,6 +497,9 @@ main() {
443497 test_missing_file_is_noop
444498 test_backup_not_overwritten
445499 test_crlf_tolerated
500+ test_extract_key_preserves_literal_backslash
501+ test_extract_key_resolves_recognized_escapes
502+ test_extract_key_escaped_close_quote_no_real_close
446503 test_marker_no_emits_private_true_alongside
447504 test_marker_yes_emits_private_false_alongside
448505 test_marker_uppercase_tolerated
0 commit comments