Skip to content

Large branch bodies panic at runtime because jump displacements overflow i16 #158

Description

@ajbufort

A forward jump over a large branch body panics at runtime because the jump displacement is written with a u16 bound check but decoded as an i16.

Minimal reproduction (no and/or needed - plain if):

>> if (false()) then (count([ ...13000 members... ]) = 999) else false()
thread 'main' panicked: index out of bounds

The then branch here compiles to more than 32KB of bytecode. FunctionBuilder::patch_jump checks the offset against u16::MAX and writes two little-endian bytes, but Instruction::Jump/JumpIfTrue/JumpIfFalse hold an i16 and the VM decodes with i16::from_le_bytes, so an offset in 32768..=65535 wraps to a negative displacement and the VM jumps backward past the start of the chunk. An offset above 65535 hits the panic!("jump too far") in patch_jump instead of returning an error.

This affects every construct that emits a forward jump over a branch: if/then/else, quantified expressions, xsl:iterate, and so on. It is reachable from any sufficiently large (but not deeply nested) branch body.

I have a fix that widens the jump displacement to i32.

-Tony Bufort

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions