Skip to content

sas7bcat: compare block pointers three-way instead of subtracting - #420

Merged
evanmiller merged 1 commit into
WizardMac:devfrom
ziyziy89:sas7bcat-block-pointer-sort
Oct 27, 2026
Merged

evanmiller merged 1 commit into
WizardMac:devfrom
ziyziy89:sas7bcat-block-pointer-sort

Conversation

@ziyziy89

Copy link
Copy Markdown
Contributor

compare_block_pointers in the SAS7BCAT catalog reader returns a 64-bit subtraction truncated to int. The values it sorts pack the catalog page number into the high 32 bits ((page << 32) + pos, with page read from the file), so two block pointers on different pages differ only above bit 32 and the truncated result loses that difference. Pointers on pages 1 and 2 compare as equal, and a descending set is left unsorted, so qsort runs with a comparator that violates the required total order (undefined behavior, and out-of-bounds reads in some qsort implementations) and the adjacent-duplicate removal in sas7bcat_uniq_index no longer works, reading and emitting the same catalog block twice.

Compare the two values three-way instead, the same way dta_compare_strls and dta_compare_value_labels already do in this codebase (the latter with a comment about this exact overflow). Reproducer with the current code: compare((1<<32), (2<<32)) returns 0, and qsort of {3<<32, 2<<32, 1<<32} leaves the array in descending order; with the fix it sorts ascending.

@evanmiller
evanmiller merged commit d7765c5 into WizardMac:dev Oct 27, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants