Skip to content

fix(kdtree): guard against zero-dimensional attributes and heap-allocate decoder (fixes #1103) - #1224

Open
jdymitarai wants to merge 1 commit into
google:mainfrom
jdymitarai:fix-kdtree-zero-dimension-crash
Open

fix(kdtree): guard against zero-dimensional attributes and heap-allocate decoder (fixes #1103)#1224
jdymitarai wants to merge 1 commit into
google:mainfrom
jdymitarai:fix-kdtree-zero-dimension-crash

Conversation

@jdymitarai

Copy link
Copy Markdown

Summary of Changes

Fixes #1103 (Crash/SEGV in draco::DecoderBuffer::Peek / DynamicIntegerPointsKdTreeDecoder due to unvalidated 0-dimensional attribute decoding).

Problem

  1. When malformed input provides 0 attributes or attributes with 0 components, total_dimensionality in KdTreeAttributesDecoder evaluates to 0. A 0-dimensional KdTree is invalid (point clouds require at least 1 spatial dimension), and passing dimension_ == 0 into DynamicIntegerPointsKdTreeDecoder causes:
    • Modulo by zero in DRACO_INCREMENT_MOD(last_axis, dimension_)
    • Access to empty levels_ and base_stack_ vectors
    • Invalid iterator read/write in PointAttributeVectorOutputIterator
  2. Instantiating DynamicIntegerPointsKdTreeDecoder<level_t> on the stack in DecodePoints() creates significant stack bloat across all compression levels (0 through 6), which can trigger stack buffer exhaustion.

Fix

  1. Validate total_dimensionality > 0 in KdTreeAttributesDecoder::DecodePortableAttributes() and DecodeDataNeededByPortableTransforms().
  2. Validate dimension_ > 0 in DynamicIntegerPointsKdTreeDecoder::DecodePoints().
  3. Allocate DynamicIntegerPointsKdTreeDecoder on the heap via std::unique_ptr in DecodePoints() to minimize stack frame size.
  4. Added unit test RejectZeroDimensionalAttributes in src/draco/compression/point_cloud/point_cloud_kd_tree_encoding_test.cc.

…ate decoder (fixes google#1103)

In KdTreeAttributesDecoder::DecodePortableAttributes() and DecodeDataNeededByPortableTransforms(),
when malformed input specifies 0 attributes or 0 components across attributes,
total_dimensionality evaluates to 0.

A 0-dimensional KdTree causes division by zero in DRACO_INCREMENT_MOD(last_axis, dimension_),
out-of-bounds index on empty level/base vectors, and invalid memory dereferences (CWE-476 / CWE-125).

Furthermore, allocating DynamicIntegerPointsKdTreeDecoder<level_t> on the stack inside
DecodePoints creates heavy stack frame overhead with nested decoder arrays, which can
cause stack-buffer-overflows in tight stack environments.

This commit:
1. Validates total_dimensionality > 0 in DecodePortableAttributes() and DecodeDataNeededByPortableTransforms().
2. Validates dimension_ > 0 in DynamicIntegerPointsKdTreeDecoder::DecodePoints().
3. Dynamically allocates DynamicIntegerPointsKdTreeDecoder on the heap via std::unique_ptr in DecodePoints().
4. Adds a unit test RejectZeroDimensionalAttributes in point_cloud_kd_tree_encoding_test.cc.

Fixes google#1103.
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.

[BUG] A SEGV in draco::DecoderBuffer::Peek<unsigned int>(unsigned int*) at decoder_buffer.h:89:9

1 participant