. "$BST_LIB" # minIni 1.2b (CompuPhase) — a .INI reader/writer in 831 lines of C89, and the # THIRD INI parser on this image beside libinih and iniparser. There is no CLI # and no consumer here, so the whole payload is /usr/include/minini/minIni.h and # minGlue.h (-dev) and /usr/lib/libminini.a (-staticdev). # # --------------------------------------------------------------------------- # WHY THIS SUITE RUNS A PROBE INSTEAD OF STOPPING AT PAYLOAD SHAPE # # BRINTOS-217 is why: oniguruma COMPILED and PACKAGED perfectly on this arm and # then returned silently wrong offsets to every caller, so a payload-only suite # would have gone green on the exact defect the port existed to find. # # But minIni's exposure is unlike every sibling on this Epic. It has no data # structure of its own and holds no state between calls: each of its ten entry # points opens a FILE*, walks it with fgets, and closes it. So what this suite # measures is not the library's own arithmetic — it is the PLATFORM SURFACES the # library stands on, and the coroutinize pass's own census says the probe is # aimed at transformed code rather than at generic API surface. All ten entry # points are coroutinized in the consumer link (refused=0), along with the # internals that carry the write path — getkeystring, cache_flush, close_rename, # save_strncpy, writekey — and glibc's _IO_fgets, _IO_fputs, _IO_new_fsetpos, # _IO_new_fgetpos and __getdelim. # # The groups written for platform reasons rather than for minIni's, and the ones # to read first on a red run: # # browse-* AN INDIRECT CALL through a caller-supplied function # rt-browse-* bulk-browse-* # pointer, made from inside a coroutinized frame — and its # three arguments point into ini_browse's own 512-byte # stack buffer at three computed offsets, since section, # key and value are packed end to end there. No sibling # port on this Epic had a callback API to press on. The # pass gives browse_cb its own DISCARD-CONSUME-GUARD and # 2b-unwind-check as natret-by-value-cascade-flat, so this # really is the transformed indirect path. # puts-* rt-* bulk-* fgetpos/fsetpos, on which the WHOLE write path depends: # cache_flush seeks BACK to a saved mark and re-reads. A # broken file position corrupts the file instead of # failing, which is why these cases assert the RESULTING # BYTES and the resulting SIZE, not just a read-back of # the one key that changed. # puts-temp-removed remove(2) then rename(2), in that order — close_rename # bulk-temp-removed REMOVES THE TARGET FIRST, so a substrate whose rename # does not work destroys the file rather than leaving it # stale. These two assert the temp file is gone. # gets-* getl-* fgets line reading, strtol base-10/base-16, strtod, # getf-* getbool-* toupper and strncasecmp — libc, through the parser. # cap-* the INI_BUFFERSIZE (512) truncation boundary on write. # # EVERY EXPECTED VALUE IS THE VALUE A NATIVE x86_64 BUILD OF THE IDENTICAL # RELEASE PRODUCES. The probe compares each value internally and prints it on # both the OK and the FAIL path, so a target run can be diffed against the # native control line by line rather than compared by tally — and that diff is # made HERE, IN THE GUEST, against the shipped control (see the end of this # file). # # THE ONE PLACE THE TWO ARMS LEGITIMATELY DIFFER IS AN UPSTREAM OUT-OF-BOUNDS # READ, and it is pinned rather than hidden. cache_flush ends with # strcmp(buffer + pos - strlen("\n"), "\n") while pos is still 0 when it is # called with *size == 0, so it reads ONE BYTE BEFORE ini_puts's own 512-byte # stack array. ASan on the native control names it exactly: "stack-buffer- # overflow ... offset 159 underflows LocalBuffer [160, 672)". The byte it reads # decides whether a newline is written first, so the resulting file depends on # stack residue and differs between two builds of the same source. It is reached # by the most ordinary write there is — appending the first key to a file ending # in a bare section header, and appending to an existing empty file. The # emptyfile-*/bareheader-* cases therefore assert only what IS defined, and the # two MI-RESIDUE lines carrying this arm's actual bytes are excluded from the # byte-diff and pinned separately below. # # The suite uses builtin `case` matching over variables read ONCE, never # `check_out ... cat` per case: on this runtime the forking is the cost rather # than the work, and the cjson suite next door was killed by the runner's # per-suite bound at 156 cases written the other way. This suite is 192 cases # and forks four times in total — two greps over the archive, the probe, and the # on-target byte-diff. # --------------------------------------------------------------------------- hdr=/usr/include/minini/minIni.h glue=/usr/include/minini/minGlue.h lib=/usr/lib/libminini.a nl=' ' # hasfile -- ok iff is a non-empty regular file. # has -- ok iff contains the literal . # hasline -- ok iff carries as a WHOLE line. hasfile() { if [ -s "$2" ]; then bst_ok "$1"; else bst_notok "$1" "absent or empty: $2"; fi; } has() { case "$3" in *"$2"*) bst_ok "$1" ;; *) bst_notok "$1" "not found: $2" ;; esac; } hasline() { case "$nl$3$nl" in *"$nl$2$nl"*) bst_ok "$1" ;; *) bst_notok "$1" "not in archive: $2" ;; esac; } # An image built without minini is a coverage gap, not a failure: skip once and # stop rather than reporting 185 reds for an absent package. if [ ! -s "$lib" ]; then bst_skip minini/present "libminini.a not installed on this image" exit 0 fi bst_ok minini/present # --- the shipped payload ----------------------------------------------------- # Upstream's own install layout, kept by the bbappend: both headers under a # per-package directory, and minGlue-stdio.h installed under the name minGlue.h # because minIni.h includes "minGlue.h" unconditionally. hasfile minini/header "$hdr" hasfile minini/glue "$glue" hasfile minini/archive "$lib" # There is deliberately no minini/no-shared-object case: shared objects are # refused distro-wide on this arm, so an absent libminini.so is the distro's # property and not this port's, and every sibling library would assert it too. # What IS this port's property is that the archive exists at all, since meta-oe's # recipe builds only a .so and its -shared link cannot happen here. # --- what the installed headers must carry ----------------------------------- # INI_BUFFERSIZE fixes every stack buffer in the library and therefore the # truncation boundary the cap-* cases measure; INI_REAL being defined by the glue # header is what compiles ini_getf/ini_putf in at all. A header that stopped # carrying either would change values below rather than fail to build. hdrtext=$(cat "$hdr" 2>/dev/null) gluetext=$(cat "$glue" 2>/dev/null) has minini/hdr-buffersize "define INI_BUFFERSIZE 512" "$hdrtext" has minini/hdr-callback-type "typedef int (*INI_CALLBACK)" "$hdrtext" has minini/hdr-tchar "define mTCHAR char" "$hdrtext" has minini/glue-filetype "define INI_FILETYPE" "$gluetext" has minini/glue-real "define INI_REAL" "$gluetext" has minini/glue-fgetpos "fgetpos" "$gluetext" has minini/glue-fsetpos "fsetpos" "$gluetext" has minini/glue-rename "rename" "$gluetext" # --- symbol completeness, derived from the INSTALLED header ------------------- # Every ini_* function the installed header declares must be a real symbol of the # installed archive, so a partial compile, a visibility mistake or a # header/library skew all fail this. The list is DERIVED from the header rather # than written here, so it survives a version bump. Note ini_getf and ini_putf # are only declared because minGlue.h defines INI_REAL — if the glue header ever # stopped doing so, the count below would change rather than silently shrink. arcsyms=$(grep -ao 'ini_[A-Za-z0-9_]*' "$lib" 2>/dev/null | sort -u) hdrsyms=$(grep -v '^[[:space:]]*#' "$hdr" 2>/dev/null \ | grep -oE '\bini_[A-Za-z0-9_]*\(' | sed 's/($//;s/(//' | sort -u) nsym=0 nmiss=0 missing="" for f in $hdrsyms; do nsym=$((nsym + 1)) case "$nl$arcsyms$nl" in *"$nl$f$nl"*) ;; *) nmiss=$((nmiss + 1)); missing="$missing $f" ;; esac done if [ "$nmiss" -eq 0 ]; then bst_ok minini/symbols-complete else bst_notok minini/symbols-complete "$nmiss missing:$missing" fi check_eq minini/symbols-count 10 "$nsym" # A spot-check that the derivation above is really reading the archive and not an # empty string that would make the loop vacuously green. hasline minini/sym-gets ini_gets "$arcsyms" hasline minini/sym-getl ini_getl "$arcsyms" hasline minini/sym-getbool ini_getbool "$arcsyms" hasline minini/sym-getf ini_getf "$arcsyms" hasline minini/sym-getsection ini_getsection "$arcsyms" hasline minini/sym-getkey ini_getkey "$arcsyms" hasline minini/sym-browse ini_browse "$arcsyms" hasline minini/sym-puts ini_puts "$arcsyms" hasline minini/sym-putl ini_putl "$arcsyms" hasline minini/sym-putf ini_putf "$arcsyms" # --- the library RUNNING, via the cross-linked probe ------------------------- # data/minini-probe is cross-linked with wasmcc-glibc against THE VERY ARCHIVE # THAT SHIPS (/usr/lib/libminini.a); its source is src/minini_probe.c. It is run # ONCE and its exit status kept, rather than re-run for the rc case: on this # runtime a multi-MB wasm module's start-up dominates the whole suite's cost. # The probe writes its scratch INI files under $TMPDIR. probe=${TMPDIR:-/tmp}/bst-minini-probe.$$ scratch=${TMPDIR:-/tmp}/bst-minini-scratch.$$ if cp "$BST_DATA/minini-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null \ && mkdir -p "$scratch" 2>/dev/null; then out=$("$probe" "$scratch" 2>&1); prc=$? # --- fixture (2) --- has minini/run-fixture-write "MI-fixture-write OK" "$out" has minini/run-fixture-size "MI-fixture-size OK" "$out" # --- gets (32) --- has minini/run-gets-basic "MI-gets-basic OK" "$out" has minini/run-gets-semicolon-comment "MI-gets-semicolon-comment OK" "$out" has minini/run-gets-second-section "MI-gets-second-section OK" "$out" has minini/run-gets-section-scoped "MI-gets-section-scoped OK" "$out" has minini/run-gets-case-insensitive "MI-gets-case-insensitive OK" "$out" has minini/run-gets-key-case-fold "MI-gets-key-case-fold OK" "$out" has minini/run-gets-whitespace-stripped "MI-gets-whitespace-stripped OK" "$out" has minini/run-gets-dequoted "MI-gets-dequoted OK" "$out" has minini/run-gets-hash-in-quotes "MI-gets-hash-in-quotes OK" "$out" has minini/run-gets-backslash-escape "MI-gets-backslash-escape OK" "$out" has minini/run-gets-doubled-quote "MI-gets-doubled-quote OK" "$out" has minini/run-gets-empty-value "MI-gets-empty-value OK" "$out" has minini/run-gets-missing-key "MI-gets-missing-key OK" "$out" has minini/run-gets-missing-section "MI-gets-missing-section OK" "$out" has minini/run-gets-missing-file "MI-gets-missing-file OK" "$out" has minini/run-gets-no-section "MI-gets-no-section OK" "$out" has minini/run-gets-colon-separator "MI-gets-colon-separator OK" "$out" has minini/run-gets-no-section-stops-at-bracket "MI-gets-no-section-stops-at-bracket OK" "$out" has minini/run-gets-truncated "MI-gets-truncated OK" "$out" has minini/run-gets-buffersize-1 "MI-gets-buffersize-1 OK" "$out" has minini/run-gets-null-buffer "MI-gets-null-buffer OK" "$out" has minini/run-gets-zero-buffersize "MI-gets-zero-buffersize OK" "$out" has minini/run-gets-null-key "MI-gets-null-key OK" "$out" has minini/run-gets-long-value-len "MI-gets-long-value-len OK" "$out" has minini/run-gets-long-value-head "MI-gets-long-value-head OK" "$out" has minini/run-gets-long-value-tail "MI-gets-long-value-tail OK" "$out" has minini/run-getsection-0 "MI-getsection-0 OK" "$out" has minini/run-getsection-1 "MI-getsection-1 OK" "$out" has minini/run-getsection-2 "MI-getsection-2 OK" "$out" has minini/run-getsection-past-end "MI-getsection-past-end OK" "$out" has minini/run-getsection-negative "MI-getsection-negative OK" "$out" has minini/run-getsection-count "MI-getsection-count OK" "$out" # --- getl (9) --- has minini/run-getl-decimal "MI-getl-decimal OK" "$out" has minini/run-getl-negative "MI-getl-negative OK" "$out" has minini/run-getl-hex-lower-x "MI-getl-hex-lower-x OK" "$out" has minini/run-getl-hex-upper-x "MI-getl-hex-upper-x OK" "$out" has minini/run-getl-leading-zero-is-decimal "MI-getl-leading-zero-is-decimal OK" "$out" has minini/run-getl-missing-key-default "MI-getl-missing-key-default OK" "$out" has minini/run-getl-empty-value-default "MI-getl-empty-value-default OK" "$out" has minini/run-getl-non-numeric "MI-getl-non-numeric OK" "$out" has minini/run-getl-missing-section-default "MI-getl-missing-section-default OK" "$out" # --- getbool (7) --- has minini/run-getbool-yes "MI-getbool-yes OK" "$out" has minini/run-getbool-false "MI-getbool-false OK" "$out" has minini/run-getbool-junk-default-1 "MI-getbool-junk-default-1 OK" "$out" has minini/run-getbool-junk-default-0 "MI-getbool-junk-default-0 OK" "$out" has minini/run-getbool-one-is-true "MI-getbool-one-is-true OK" "$out" has minini/run-getbool-missing-default "MI-getbool-missing-default OK" "$out" has minini/run-getbool-empty-default "MI-getbool-empty-default OK" "$out" # --- getf (4) --- has minini/run-getf-value "MI-getf-value OK" "$out" has minini/run-getf-integer-value "MI-getf-integer-value OK" "$out" has minini/run-getf-missing-default "MI-getf-missing-default OK" "$out" has minini/run-getf-non-numeric "MI-getf-non-numeric OK" "$out" # --- getkey (8) --- has minini/run-getkey-0 "MI-getkey-0 OK" "$out" has minini/run-getkey-1 "MI-getkey-1 OK" "$out" has minini/run-getkey-past-end "MI-getkey-past-end OK" "$out" has minini/run-getkey-third-0 "MI-getkey-third-0 OK" "$out" has minini/run-getkey-missing-section "MI-getkey-missing-section OK" "$out" has minini/run-getkey-no-section-0 "MI-getkey-no-section-0 OK" "$out" has minini/run-getkey-no-section-1 "MI-getkey-no-section-1 OK" "$out" has minini/run-getkey-first-count "MI-getkey-first-count OK" "$out" # --- browse (13) --- has minini/run-browse-rc "MI-browse-rc OK" "$out" has minini/run-browse-calls "MI-browse-calls OK" "$out" has minini/run-browse-head "MI-browse-head OK" "$out" has minini/run-browse-first-section "MI-browse-first-section OK" "$out" has minini/run-browse-dequotes "MI-browse-dequotes OK" "$out" has minini/run-browse-second-section "MI-browse-second-section OK" "$out" has minini/run-browse-tail "MI-browse-tail OK" "$out" has minini/run-browse-skips-comments "MI-browse-skips-comments OK" "$out" has minini/run-browse-early-stop-rc "MI-browse-early-stop-rc OK" "$out" has minini/run-browse-early-stop-calls "MI-browse-early-stop-calls OK" "$out" has minini/run-browse-early-stop-text "MI-browse-early-stop-text OK" "$out" has minini/run-browse-null-callback "MI-browse-null-callback OK" "$out" has minini/run-browse-missing-file "MI-browse-missing-file OK" "$out" # --- puts (22) --- has minini/run-puts-setup "MI-puts-setup OK" "$out" has minini/run-puts-change-rc "MI-puts-change-rc OK" "$out" has minini/run-puts-change-bytes "MI-puts-change-bytes OK" "$out" has minini/run-puts-temp-removed "MI-puts-temp-removed OK" "$out" has minini/run-puts-change-readback "MI-puts-change-readback OK" "$out" has minini/run-puts-idempotent-rc "MI-puts-idempotent-rc OK" "$out" has minini/run-puts-idempotent-bytes "MI-puts-idempotent-bytes OK" "$out" has minini/run-puts-add-key-rc "MI-puts-add-key-rc OK" "$out" has minini/run-puts-add-key-bytes "MI-puts-add-key-bytes OK" "$out" has minini/run-puts-add-section-rc "MI-puts-add-section-rc OK" "$out" has minini/run-puts-add-section-bytes "MI-puts-add-section-bytes OK" "$out" has minini/run-puts-del-key-rc "MI-puts-del-key-rc OK" "$out" has minini/run-puts-del-key-bytes "MI-puts-del-key-bytes OK" "$out" has minini/run-puts-del-key-readback "MI-puts-del-key-readback OK" "$out" has minini/run-puts-del-section-rc "MI-puts-del-section-rc OK" "$out" has minini/run-puts-del-section-bytes "MI-puts-del-section-bytes OK" "$out" has minini/run-puts-append-in-last-section-rc "MI-puts-append-in-last-section-rc OK" "$out" has minini/run-puts-append-in-last-section-bytes "MI-puts-append-in-last-section-bytes OK" "$out" has minini/run-puts-create-rc "MI-puts-create-rc OK" "$out" has minini/run-puts-create-bytes "MI-puts-create-bytes OK" "$out" has minini/run-puts-delete-missing-file-rc "MI-puts-delete-missing-file-rc OK" "$out" has minini/run-puts-delete-missing-file-absent "MI-puts-delete-missing-file-absent OK" "$out" # --- quote (13) --- has minini/run-quote-setup "MI-quote-setup OK" "$out" has minini/run-quote-hash-rc "MI-quote-hash-rc OK" "$out" has minini/run-quote-hash-bytes "MI-quote-hash-bytes OK" "$out" has minini/run-quote-hash-roundtrip "MI-quote-hash-roundtrip OK" "$out" has minini/run-quote-semi-rc "MI-quote-semi-rc OK" "$out" has minini/run-quote-semi-roundtrip "MI-quote-semi-roundtrip OK" "$out" has minini/run-quote-dquote-rc "MI-quote-dquote-rc OK" "$out" has minini/run-quote-dquote-bytes "MI-quote-dquote-bytes OK" "$out" has minini/run-quote-dquote-roundtrip "MI-quote-dquote-roundtrip OK" "$out" has minini/run-quote-trailing-space-rc "MI-quote-trailing-space-rc OK" "$out" has minini/run-quote-trailing-space-roundtrip "MI-quote-trailing-space-roundtrip OK" "$out" has minini/run-quote-plain-not-quoted-rc "MI-quote-plain-not-quoted-rc OK" "$out" has minini/run-quote-plain-not-quoted-bytes "MI-quote-plain-not-quoted-bytes OK" "$out" # --- num-setup (1) --- has minini/run-num-setup "MI-num-setup OK" "$out" # --- putl (11) --- has minini/run-putl-rc "MI-putl-rc OK" "$out" has minini/run-putl-roundtrip "MI-putl-roundtrip OK" "$out" has minini/run-putl-negative-rc "MI-putl-negative-rc OK" "$out" has minini/run-putl-negative-roundtrip "MI-putl-negative-roundtrip OK" "$out" has minini/run-putl-zero-rc "MI-putl-zero-rc OK" "$out" has minini/run-putl-zero-roundtrip "MI-putl-zero-roundtrip OK" "$out" has minini/run-putl-int32-max-rc "MI-putl-int32-max-rc OK" "$out" has minini/run-putl-int32-max-roundtrip "MI-putl-int32-max-roundtrip OK" "$out" has minini/run-putl-int32-min-rc "MI-putl-int32-min-rc OK" "$out" has minini/run-putl-int32-min-roundtrip "MI-putl-int32-min-roundtrip OK" "$out" has minini/run-putl-bytes "MI-putl-bytes OK" "$out" # --- putf (3) --- has minini/run-putf-rc "MI-putf-rc OK" "$out" has minini/run-putf-text "MI-putf-text OK" "$out" has minini/run-putf-roundtrip "MI-putf-roundtrip OK" "$out" # --- rt (14) --- has minini/run-rt-setup "MI-rt-setup OK" "$out" has minini/run-rt-20-writes "MI-rt-20-writes OK" "$out" has minini/run-rt-20-keys "MI-rt-20-keys OK" "$out" has minini/run-rt-first-key "MI-rt-first-key OK" "$out" has minini/run-rt-last-key "MI-rt-last-key OK" "$out" has minini/run-rt-browse-rc "MI-rt-browse-rc OK" "$out" has minini/run-rt-browse-calls "MI-rt-browse-calls OK" "$out" has minini/run-rt-browse-tail "MI-rt-browse-tail OK" "$out" has minini/run-rt-size "MI-rt-size OK" "$out" has minini/run-rt-20-rewrites "MI-rt-20-rewrites OK" "$out" has minini/run-rt-rewrite-size "MI-rt-rewrite-size OK" "$out" has minini/run-rt-rewrite-keys "MI-rt-rewrite-keys OK" "$out" has minini/run-rt-rewrite-mid "MI-rt-rewrite-mid OK" "$out" has minini/run-rt-rewrite-browse-calls "MI-rt-rewrite-browse-calls OK" "$out" # --- bulk (10) --- has minini/run-bulk-setup "MI-bulk-setup OK" "$out" has minini/run-bulk-60-writes "MI-bulk-60-writes OK" "$out" has minini/run-bulk-size "MI-bulk-size OK" "$out" has minini/run-bulk-rewrite-first-rc "MI-bulk-rewrite-first-rc OK" "$out" has minini/run-bulk-rewrite-first-value "MI-bulk-rewrite-first-value OK" "$out" has minini/run-bulk-tail-intact "MI-bulk-tail-intact OK" "$out" has minini/run-bulk-key-count "MI-bulk-key-count OK" "$out" has minini/run-bulk-browse-calls "MI-bulk-browse-calls OK" "$out" has minini/run-bulk-size-after "MI-bulk-size-after OK" "$out" has minini/run-bulk-temp-removed "MI-bulk-temp-removed OK" "$out" # --- emptyfile (4) --- has minini/run-emptyfile-setup "MI-emptyfile-setup OK" "$out" has minini/run-emptyfile-puts-rc "MI-emptyfile-puts-rc OK" "$out" has minini/run-emptyfile-readback "MI-emptyfile-readback OK" "$out" has minini/run-emptyfile-section "MI-emptyfile-section OK" "$out" # --- bareheader (4) --- has minini/run-bareheader-setup "MI-bareheader-setup OK" "$out" has minini/run-bareheader-puts-rc "MI-bareheader-puts-rc OK" "$out" has minini/run-bareheader-readback "MI-bareheader-readback OK" "$out" has minini/run-bareheader-key-count "MI-bareheader-key-count OK" "$out" # --- cap (4) --- has minini/run-cap-setup "MI-cap-setup OK" "$out" has minini/run-cap-puts-rc "MI-cap-puts-rc OK" "$out" has minini/run-cap-truncated-len "MI-cap-truncated-len OK" "$out" has minini/run-cap-truncated-content "MI-cap-truncated-content OK" "$out" # The pointer width and the arm's long size, which are the TWO lines that must # legitimately differ between the control and this arm — and so are excluded # from the byte-diff below rather than allowed to fail it. `long` is 32-bit # here and 64-bit on the control, which is why every numeric case above stays # inside int32 range. has minini/run-pointer-width "MI-PROBE minini probe, 32-bit pointers" "$out" has minini/run-arch-long "MI-ARCH sizeof(long)=4 LONG_MAX=2147483647 INI_BUFFERSIZE=512" "$out" # THE UPSTREAM OUT-OF-BOUNDS READ, pinned as THIS ARM'S measured bytes. See the # header comment: cache_flush reads buffer[-1] when it is called with *size == # 0, and the byte it finds decides whether a newline is emitted first. Both # cases are asserted for what is defined (rc + read-back, above) and the actual # resulting file is pinned here, so a platform-side change to what sits below # that stack array shows up as a CHANGED VALUE instead of going unnoticed. # They are excluded from the native byte-diff on principle rather than on # observation: the value is undefined by the language, so it is not something a # cross-arm comparison may assert. As measured, the two arms happen to AGREE on # both — the byte below that stack array is the same on x86_64 and wasm32-hwjs # today — which is worth knowing and worth not depending on. has minini/residue-emptyfile "MI-RESIDUE emptyfile [\n[E]\nk=v\n]" "$out" has minini/residue-bareheader "MI-RESIDUE bareheader [[R]\n\nk=v\n]" "$out" # BYTE-IDENTITY AGAINST THE NATIVE CONTROL, asserted here ON TARGET rather than # by eyeballing two logs off-target. data/minini-native.txt is the verbatim # output of this same probe source built natively against a host build of the # identical release, with the two arm-dependent banners and the two MI-RESIDUE # lines removed. Comparing it inside the guest keeps any terminal capture out # of the comparison — the console dump truncates long lines, and this probe # prints whole INI files as single lines, which is exactly how an off-target # diff of this output would mislead — and it turns "matches native" from a # one-off manual check into a permanent regression guard: a platform change in # libc line reading, number conversion or file positioning shows up as a # CHANGED VALUE here even if every verdict above still passes. ctl=$BST_DATA/minini-native.txt gotf=${TMPDIR:-/tmp}/bst-minini-got.$$ printf '%s\n' "$out" | grep -vE '^MI-(PROBE|ARCH|RESIDUE) ' > "$gotf" 2>/dev/null if [ ! -s "$ctl" ]; then bst_notok minini/native-byte-identical "control absent or empty: $ctl" elif cmp -s "$ctl" "$gotf"; then bst_ok minini/native-byte-identical else bst_notok minini/native-byte-identical \ "first diff: $(diff "$ctl" "$gotf" 2>/dev/null | sed -n '2,3p' | tr '\n' ' ' | cut -c1-90)" fi rm -f "$gotf" # The probe's own tally and its exit status. 161/161 is what the same source # scores natively against a host build of the identical release. has minini/run-summary "MI-SUMMARY 161/161" "$out" check_eq minini/run-exit0 0 "$prc" rm -rf "$probe" "$scratch" else bst_notok minini/run-stage "cannot stage $BST_DATA/minini-probe" fi