Skip to content

Arrow import ignores the file's declared Int/Float/FixedSizeBinary/Decimal parameters #881

Description

@jdatcmd

What is unchecked

imp_apply_field in src/columnar_arrow.c inspects exactly three Arrow type tags — Date,
Time and Timestamp — with default: break for everything else. So on import the file's
declared

  • Int.bitWidth and Int.is_signed
  • floating-point width
  • FixedSizeBinary.byteWidth
  • Decimal precision and scale

are never read. The stride and interpretation come from the target PostgreSQL column rather
than from the file. This is the same class of defect as #864/#865, which #870 fixed for the
temporal types only.

What is already safe, so this is not a memory-safety report

The import validates buffer lengths: "value buffer too small for the row count". Any case
where the file's carrier is narrower than the target — float16 into float8,
fixed_size_binary(8) into uuid, int32 into bigint — is refused as corrupt rather than
read out of bounds.

What survives that check, and is therefore silent

Cases where the carrier matches or exceeds the target:

file declares column what should happen
uint64 bigint values >= 2^63 are read as negative
int64 int / smallint stride is the target's, so values are read from the wrong offsets
decimal128(10,2) numeric(20,4) same 16-byte carrier, wrong scale — values off by powers of ten

Status of this report

Read from the code, not measured. I have verified the three-tag limit and the buffer-length
check by reading main; the three outcomes above follow from them but I have not run any of
them. Whoever picks this up should start by building the corpus files and making each one fail
before writing a fix — test/arrow_corpus.py already emits typed Arrow fixtures via pyarrow and
is the natural place to add them.

Prior art

#861 was written to cover exactly this, alongside a temporal policy that has since been decided
the other way (see the closing comment there, and #880). Its non-temporal arms are worth reading
before starting, but not rebasing: that branch predates #870 and its head had deleted its own
Int.is_signed check, so its uint64 into bigint arm was red on its own terms.

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