DF-0871 / harness_fixed.c
/* * DF-0871 FIXED harness. * * Identical to harness.c but the do/while is bounded to j < 64 (== the * destination array length == the source array length, NTFS_ATTRNAME_MAXLEN) * and the destination is explicitly NUL-terminated. This is exactly the fix * in fix.diff. No guard fault, no overflow. * * Build: cc -O2 -o harness_fixed harness_fixed.c * Run: ./harness_fixed [num] */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> typedef uint16_t wchar_nt; struct ntvattrdef { char ad_name[0x40]; int ad_namelen; uint32_t ad_type; }; #define SRCLEN 256 static wchar_nt src_buf[SRCLEN]; static void make_evil_source(void) { for (int i = 0; i < SRCLEN - 1; i++) src_buf[i] = 0x4141; src_buf[SRCLEN - 1] = 0; } /* FIXED transcription: EXACT mirror of fix.diff -- bound the do/while to the * destination array length and force NUL-termination. This is the verbatim * patched ntfs_vfsops.c:457-464 logic. */ static void fixed_copy(struct ntvattrdef *arr, int i) { int j = 0; size_t dstlen = sizeof(arr[i].ad_name); /* = 64 (char[0x40]) */ do { arr[i].ad_name[j] = (char)src_buf[j]; } while(src_buf[j++] && j < (int)dstlen); /* Force NUL-termination within the fixed-size buffer. */ arr[i].ad_name[dstlen - 1] = '\0'; arr[i].ad_namelen = j - 1; arr[i].ad_type = 0xFFFFFFFFu; } int main(int argc, char **argv) { int num = (argc > 1) ? atoi(argv[1]) : 1; if (num < 1) num = 1; make_evil_source(); size_t allocsz = (size_t)num * sizeof(struct ntvattrdef); /* allocate a touch of padding so any stray write would be visible */ unsigned char *block = calloc(1, allocsz + 64); struct ntvattrdef *arr = (struct ntvattrdef *)block; fixed_copy(arr, num - 1); printf("[harness_fixed] DF-0871 fixed (bounded do/while, NUL-terminated) -- mirrors fix.diff\n"); printf("[harness_fixed] num=%d allocsz=%zu copy completed with NO overflow.\n", num, allocsz); printf("[harness_fixed] entry[%d].ad_namelen = %d (capped)\n", num-1, arr[num-1].ad_namelen); /* verify no byte past entry[num-1]'s object was touched */ int leak = 0; size_t start = (size_t)(num - 1) * 72 + 72; for (size_t k = start; k < allocsz + 64; k++) if (block[k] != 0) leak++; printf("[harness_fixed] bytes written past the %zu-byte allocation = %d (expect 0)\n", allocsz, leak); free(block); return leak == 0 ? 0 : 1; } |