From c0539537c70aab892fbabdc17e54af26c60113aa Mon Sep 17 00:00:00 2001 From: Sharad Boni Date: Mon, 27 Apr 2026 15:32:57 -0700 Subject: [PATCH] security: add bounds checks to decoder prediction schemes and point count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix four heap-buffer-overflow vulnerabilities in mesh prediction scheme decoders and a negative-point-count bug in the sequential decoder: 1. mesh_prediction_scheme_parallelogram_decoder.h: ComputeOriginalValues silently discarded the `size` parameter and iterated up to corner_map_size, which may exceed the actual output buffer allocation. Add a guard: corner_map_size * num_components > size. 2. mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h: Same pattern — size was ignored. Add identical guard. 3. mesh_prediction_scheme_multi_parallelogram_decoder.h: Same pattern. Add identical guard. 4. mesh_prediction_scheme_geometric_normal_decoder.h: Same pattern. Add identical guard. 5. point_cloud_sequential_decoder.cc: num_points is decoded from the bitstream as int32_t with no validation. A negative value implicitly converts to a huge uint32_t and causes downstream heap overflow. Reject negative point counts. --- ...ediction_scheme_constrained_multi_parallelogram_decoder.h | 5 ++++- .../mesh_prediction_scheme_geometric_normal_decoder.h | 5 ++++- .../mesh_prediction_scheme_multi_parallelogram_decoder.h | 5 ++++- .../mesh_prediction_scheme_parallelogram_decoder.h | 5 ++++- .../point_cloud/point_cloud_sequential_decoder.cc | 3 +++ 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h index 17899d054..36e29756c 100644 --- a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h +++ b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h @@ -82,7 +82,7 @@ template bool MeshPredictionSchemeConstrainedMultiParallelogramDecoder< DataTypeT, TransformT, MeshDataT>:: ComputeOriginalValues(const CorrType *in_corr, DataTypeT *out_data, - int /* size */, int num_components, + int size, int num_components, const PointIndex * /* entry_to_point_id_map */) { this->transform().Init(num_components); @@ -107,6 +107,9 @@ bool MeshPredictionSchemeConstrainedMultiParallelogramDecoder< const int corner_map_size = static_cast(this->mesh_data().data_to_corner_map()->size()); + if (corner_map_size * num_components > size) { + return false; + } for (int p = 1; p < corner_map_size; ++p) { const CornerIndex start_corner_id = this->mesh_data().data_to_corner_map()->at(p); diff --git a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h index badea22f3..2c32ad7bd 100644 --- a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h +++ b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h @@ -97,7 +97,7 @@ template bool MeshPredictionSchemeGeometricNormalDecoder< DataTypeT, TransformT, MeshDataT>::ComputeOriginalValues(const CorrType *in_corr, - DataTypeT *out_data, int /* size */, + DataTypeT *out_data, int size, int num_components, const PointIndex *entry_to_point_id_map) { this->SetQuantizationBits(this->transform().quantization_bits()); @@ -109,6 +109,9 @@ bool MeshPredictionSchemeGeometricNormalDecoder< const int corner_map_size = static_cast(this->mesh_data().data_to_corner_map()->size()); + if (corner_map_size * num_components > size) { + return false; + } VectorD pred_normal_3d; int32_t pred_normal_oct[2]; diff --git a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h index 9825c7261..e25d204f8 100644 --- a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h +++ b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h @@ -59,7 +59,7 @@ template bool MeshPredictionSchemeMultiParallelogramDecoder:: ComputeOriginalValues(const CorrType *in_corr, DataTypeT *out_data, - int /* size */, int num_components, + int size, int num_components, const PointIndex * /* entry_to_point_id_map */) { this->transform().Init(num_components); @@ -76,6 +76,9 @@ bool MeshPredictionSchemeMultiParallelogramDecoder(this->mesh_data().data_to_corner_map()->size()); + if (corner_map_size * num_components > size) { + return false; + } for (int p = 1; p < corner_map_size; ++p) { const CornerIndex start_corner_id = this->mesh_data().data_to_corner_map()->at(p); diff --git a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h index 4d47ddf30..8aaf651bd 100644 --- a/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h +++ b/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h @@ -56,7 +56,7 @@ template bool MeshPredictionSchemeParallelogramDecoder:: ComputeOriginalValues(const CorrType *in_corr, DataTypeT *out_data, - int /* size */, int num_components, + int size, int num_components, const PointIndex * /* entry_to_point_id_map */) { this->transform().Init(num_components); @@ -72,6 +72,9 @@ bool MeshPredictionSchemeParallelogramDecoder(this->mesh_data().data_to_corner_map()->size()); + if (corner_map_size * num_components > size) { + return false; + } for (int p = 1; p < corner_map_size; ++p) { const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p); const int dst_offset = p * num_components; diff --git a/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc b/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc index b9382d310..fa2f6eca3 100644 --- a/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc +++ b/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc @@ -24,6 +24,9 @@ bool PointCloudSequentialDecoder::DecodeGeometryData() { if (!buffer()->Decode(&num_points)) { return false; } + if (num_points < 0) { + return false; + } point_cloud()->set_num_points(num_points); return true; }