Repository navigation
Conversation
PCLBase<PCLPointCloud2>::setInputCloud took any field named x, y or z as the coordinates, whatever its datatype, count or offset, and kept the index of a previous cloud when the new cloud has no such field. The filters then read and wrote these fields as single floats, so a cloud with 1 or 2 byte coordinates (a PCD file may declare them so) was read and written past the end of its points and of its data, and a stale index read past the end of the fields. setInputCloud now resets x_idx_, y_idx_ and z_idx_ and only takes a field that holds one FLOAT32 inside a point, so that the existing UNAVAILABLE checks of the filters reject other layouts. initCompute rejects a cloud whose data is smaller than width * height * point_step. The filters that did not go through these checks now do: - CropBox checks that x, y and z are available and reads each at its own offset instead of 12 bytes from x. - CropBox and RandomSample with keep_organized write the user filter value at the checked x/y/z offsets, and use its current value instead of the first one set (it was kept in a function-static variable). - ExtractIndices with keep_organized writes the user filter value only into fields that can hold a float. - RadiusOutlierRemoval and StatisticalOutlierRemoval with keep_organized write the fill value at the x/y/z offsets instead of the first 12 bytes of the point. - ProjectInliers uses the checked x/y/z offsets of the input, which also makes it work in place (the output has no fields yet then). - PassThrough and VoxelGrid check that the filter field is a FLOAT32 inside the point (the Indices overload of PassThrough did not check its type, and a field with COUNT 0 has no bytes, so at the end of a point it was read past the point). VoxelGrid checks that the filter field exists before computing the bounds, instead of reading fields[-1]. getMinMax (PCLPointCloud2) and RangeImage::extractFarRanges, which read fields as floats outside of PCLBase, check that they are FLOAT32 and inside the data.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PCLBase<PCLPointCloud2>::setInputCloudtakes any field namedx,yorzas the coordinates, whatever its datatype, count or offset, and keeps the index of a previous cloud when the new one has no such field. ThePCLPointCloud2filters then read and write these fields as single floats. A PCD file may declare its coordinates as 1-byte or 2-byte integers (TYPE U,SIZE 1), so loading such a file and passing it toVoxelGrid,PassThrough,CropBox,ProjectInliers, ... reads (and withkeep_organized, writes) past the end of the points and of the data buffer. For example,VoxelGrid<PCLPointCloud2>on a cloud withUINT8x/y/z fields reads 4 bytes at each 1-byte field, which AddressSanitizer reports as a heap-buffer-overflow on the last point.This PR checks the layout once, where the indices are set:
setInputCloudresetsx_idx_,y_idx_andz_idx_and only takes a field that holds oneFLOAT32inside a point (with a warning otherwise), so theUNAVAILABLEchecks the filters already have reject other layouts.initComputerejects a cloud whose data is smaller thanwidth * height * point_step.CropBoxchecks that x, y and z are available and reads each at its own offset (it read 12 bytes from x, assuming y and z follow).CropBoxandRandomSamplewithkeep_organizedwrite the user filter value at the checked x/y/z offsets, and use its current value (it was kept in a function-static variable, so only the first value ever set was used).ExtractIndiceswithkeep_organizedwrites the user filter value only into fields that can hold a float (it wrote 4 bytes into every field).RadiusOutlierRemovalandStatisticalOutlierRemovalwithkeep_organizedwrite the fill value at the x/y/z offsets instead of the first 12 bytes of the point.ProjectInliersuses the checked x/y/z offsets of the input. As a side effect it now also works in place (withfilter (*cloud)the output has no fields yet whileapplyFilterruns, so the lookup by name always failed).PassThroughandVoxelGridcheck that the filter field is aFLOAT32inside the point in bothapplyFilteroverloads (theIndicesoverload ofPassThroughdid not check its type; a field withCOUNT 0in a PCD file has no bytes, so at the end of a point it was read past the point), andVoxelGridchecks that the filter field exists before computing the bounds (it readfields[-1]).getMinMax (PCLPointCloud2)andRangeImage::extractFarRanges, which read fields as floats outside ofPCLBase, check that they areFLOAT32and inside the data.Clouds made with
toPCLPointCloud2from the PCL point types, or read from PCD files with float coordinates, are not affected.Tests:
test_filtersgets one test per filter (VoxelGrid.FieldLayout*,PassThrough.FieldLayout*,CropBox.FieldLayout*,ExtractIndices.FieldLayoutKeepOrganizedSmallField,RadiusOutlierRemoval.FieldLayoutKeepOrganizedXYZOffsets,StatisticalOutlierRemoval.FieldLayoutKeepOrganizedXYZOffsets,RandomSample.FieldLayoutKeepOrganizedXYZNotFloat32,ProjectInliers.FieldLayoutXYZNotFloat32,PCLBase.FieldLayout*), andtest_commongetsPCL.GetMinMaxFieldLayoutandPCL.ExtractFarRangesFieldLayout. Built with AddressSanitizer, the wholetest_filters,test_commonandtest_common_iosuites pass with this change; without it, all 15 new tests fail (9 of them with an AddressSanitizer heap-buffer-overflow report, the others with wrong output).Related:
PCLPointCloud2::concatenatehas the same kind of layout mismatch; I will send its fix separately.VoxelGridwithdownsample_all_data(the default) also copies 8-byte fields into 4-byte slots when averaging; #6508 changes the averaging for that.This is the change from #6498, which can no longer be opened, re-opened here on today's master.