Summary
In XeTeX, \filedump offset <n> does not work correctly for larger offsets. The scanned offset is stored in a small_number before being passed to getfiledump, producing signed 16-bit truncation/wraparound on current Web2C builds.
For example:
- offset
65536 behaves like offset 0;
- offset
70000 behaves like offset 4464;
- values in
32768..65535 become negative after narrowing and therefore do not read the intended position.
Source
In texk/web2c/xetexdir/xetex.web, conv_toks declares:
@!j: integer;
...
@!i:small_number;
The \filedump branch then does:
{scan offset}
cur_val := 0;
if (scan_keyword("offset")) then begin
scan_int;
if (cur_val < 0) then begin
...
end;
end;
i := cur_val;
{scan length}
cur_val := 0;
if (scan_keyword("length")) then begin
scan_int;
...
end;
j := cur_val;
...
getfiledump(s, i, j);
This also conflicts with XeTeX's own error message in the same branch:
A file offset must be between 0 and 2^{31}-1
so the offset appears intended to remain a normal TeX integer, like the length.
This is still present in current TeX Live trunk / XeTeX 0.999998.
Expected behavior
\filedump offset <n> should use the requested non-negative offset without narrowing it to small_number.
Simple fix plan
- Store the scanned file offset in an
integer, not a small_number.
- Preferably introduce a dedicated local such as
file_offset: integer rather than reusing i, so its intended type is explicit.
- Pass that integer unchanged to
getfiledump.
The minimal fix may simply be changing the relevant temporary from small_number to integer, if widening i is otherwise harmless.
Regression test plan
Add a small XeTeX regression test with a file larger than 64 KiB containing known sentinel bytes, and check \filedump ... length 1 at offsets around the signed-16-bit and 16-bit boundaries, for example:
32767
32768
65535
65536
65537
70000
The test should verify that:
- offsets at and above
32768 are not converted to negative values;
- offsets at and above
65536 do not wrap modulo 65536;
- ordinary smaller offsets continue to behave unchanged.
Summary
In XeTeX,
\filedump offset <n>does not work correctly for larger offsets. The scanned offset is stored in asmall_numberbefore being passed togetfiledump, producing signed 16-bit truncation/wraparound on current Web2C builds.For example:
65536behaves like offset0;70000behaves like offset4464;32768..65535become negative after narrowing and therefore do not read the intended position.Source
In
texk/web2c/xetexdir/xetex.web,conv_toksdeclares:The
\filedumpbranch then does:This also conflicts with XeTeX's own error message in the same branch:
so the offset appears intended to remain a normal TeX integer, like the length.
This is still present in current TeX Live trunk / XeTeX 0.999998.
Expected behavior
\filedump offset <n>should use the requested non-negative offset without narrowing it tosmall_number.Simple fix plan
integer, not asmall_number.file_offset: integerrather than reusingi, so its intended type is explicit.getfiledump.The minimal fix may simply be changing the relevant temporary from
small_numbertointeger, if wideningiis otherwise harmless.Regression test plan
Add a small XeTeX regression test with a file larger than 64 KiB containing known sentinel bytes, and check
\filedump ... length 1at offsets around the signed-16-bit and 16-bit boundaries, for example:327673276865535655366553770000The test should verify that:
32768are not converted to negative values;65536do not wrap modulo 65536;