Skip to content

XeTeX \filedump offset is truncated to 16 bits #88

Description

@IvanaGyro

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

  1. Store the scanned file offset in an integer, not a small_number.
  2. Preferably introduce a dedicated local such as file_offset: integer rather than reusing i, so its intended type is explicit.
  3. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions