mirror of
https://dev.lirent.ru/Vatrog/vm-automation-signaling.git
synced 2026-06-25 20:36:36 +03:00
fix(discovery): tolerate CRLF line endings in mtree parsing
mtree_low_split anchored the system flatview on "Root memory region: system" followed by LF/space/EOF, but QEMU's HMP `info mtree -f` output is CRLF, so the byte after "system" is '\r'. The anchor was rejected, the parser returned 0 (fail-closed), and on a real guest the daemon never attached the VM (low=0 => ok=0). The synthetic LF-only fixture hid this; the fix is verified against the real CRLF output. Accept '\r' in the anchor check (LF-only input still works) and add a regression test that re-encodes the fixture as CRLF in memory. Bump 0.3.7.
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
# Single source of truth for the version: CI passes -DVMSIG_VERSION=${TAG#v}, so the project
|
||||
# version (-> libvgpu-perception SONAME/.so version) and the .deb version come from one tag.
|
||||
set(VMSIG_VERSION "0.3.6" CACHE STRING "Release version (MAJOR.MINOR.PATCH); CI passes the tag")
|
||||
set(VMSIG_VERSION "0.3.7" CACHE STRING "Release version (MAJOR.MINOR.PATCH); CI passes the tag")
|
||||
project(vmsig VERSION ${VMSIG_VERSION} LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 17)
|
||||
|
||||
@@ -95,10 +95,11 @@ static const char* find_system_flatview(const char* text, const char** body_end)
|
||||
const char* anchor = "Root memory region: system";
|
||||
const char* p = text;
|
||||
while ((p = strstr(p, anchor)) != NULL) {
|
||||
/* The root name must end the token (newline/EOF) — reject "system.flash0" etc.,
|
||||
* and reject roots that merely contain the word elsewhere. */
|
||||
/* The root name must end the token (CR/LF/space/EOF) — reject "system.flash0" etc.,
|
||||
* and reject roots that merely contain the word elsewhere. QEMU's HMP output is
|
||||
* CRLF, so the byte after "system" is '\r'; accept it (LF-only input also works). */
|
||||
const char* after = p + strlen(anchor);
|
||||
if (*after == '\n' || *after == '\0' || *after == ' ') {
|
||||
if (*after == '\n' || *after == '\0' || *after == ' ' || *after == '\r') {
|
||||
const char* body = strchr(p, '\n');
|
||||
if (!body) return NULL;
|
||||
body++; /* first region line */
|
||||
|
||||
@@ -32,6 +32,18 @@ static char* slurp(const char* path) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Re-encode every '\n' as '\r\n' (QEMU's HMP output is CRLF). Caller frees; NULL on OOM. */
|
||||
static char* to_crlf(const char* lf) {
|
||||
size_t n = 0, extra = 0;
|
||||
for (const char* p = lf; *p; p++) { n++; if (*p == '\n') extra++; }
|
||||
char* out = malloc(n + extra + 1);
|
||||
if (!out) return NULL;
|
||||
char* o = out;
|
||||
for (const char* p = lf; *p; p++) { if (*p == '\n') *o++ = '\r'; *o++ = *p; }
|
||||
*o = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Case B: a minimal, NON-fragmented system flatview — one big GPA-0 ram run plus high-RAM
|
||||
* carrying @<low>. Must not be broken by the new parser. */
|
||||
static const char* k_happy =
|
||||
@@ -65,6 +77,16 @@ int main(void) {
|
||||
/* E: the decoy (non-system) flatview comes FIRST and carries @0x40000000; the
|
||||
* function must select the SYSTEM flatview (@0x80000000), not the decoy. */
|
||||
CHECK(low != 0x40000000ull, "E: decoy flatview @offset rejected (system AS chosen)");
|
||||
/* F: real QEMU HMP output is CRLF. The parser MUST tolerate '\r' — a synthetic
|
||||
* LF-only fixture hid this, so the shipped parser returned 0 on the real VM mtree
|
||||
* (-> low=0 -> VM never attached). Regression guard, independent of how git stores
|
||||
* the fixture's line endings. */
|
||||
char* frag_crlf = to_crlf(frag);
|
||||
CHECK(frag_crlf != NULL, "F: CRLF copy allocated");
|
||||
if (frag_crlf) {
|
||||
CHECK(mtree_low_split(frag_crlf) == 0x80000000ull, "F: CRLF fragmented split == 0x80000000");
|
||||
free(frag_crlf);
|
||||
}
|
||||
free(frag);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user