When compiling with -march=znver4 (or any arch with FMA), GCC's default
-ffp-contract=fast contracts a*b+c into FMA opportunistically. The same
inline math function compiled in the shared library and in the test
binary can get different FMA contraction decisions due to different
optimization contexts, producing bit-different FP results.
Three API tests compare C++ direct calls (inlined into test TU) against
C API wrapper calls (through libassimp.so) using EXPECT_EQ (bit-exact),
which fails when the compiler contracts differently across TUs.
Verified via disassembly: the library uses vfnmadd FMA instructions
(3 roundings) while the test binary uses separate vmulss+vsubss
(6 roundings) for the same computation.
Replace EXPECT_EQ with Equal(epsilon) for the three affected tests:
- aiMatrix3FromToTest: use machine epsilon (~1.19e-7)
- aiMatrix4FromToTest: use machine epsilon (~1.19e-7)
- aiQuaternionFromNormalizedQuaternionTest: use 1e-4 because FMA
differences in 1.0-x*x-y*y-z*z can flip a near-zero residual's sign,
causing w=0 vs w=sqrt(tiny)≈1e-4
Fixes#6246
Co-authored-by: Chris de Claverie <declaverie@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
* Fix conditional check in SkipSpaces function to prevent out-of-bound access.
The `SkipSpaces` function's condition was updated to ensure that the pointer check `in != end` is evaluated before dereferencing the pointer. This change prevents potential out-of-bound access when the input pointer reaches the end.
* Avoid input is wrong
* Fix all in != end
* Fix some minor bugs
* Change size to capacity
* Obj: Fix unittest
The `GetVertexColorsForType` function previously used `input->count`
(the total number of elements in the accessor) to allocate the output
array and bound the conversion loop. However, when a
`vertexRemappingTable` is provided, `ExtractData` extracts a subset of
elements matching the size of the remapping table rather than the full
accessor count.
In cases where the remapping table was smaller than the accessor count
(including empty tables), the subsequent loop would perform
out-of-bounds reads on the `colors` buffer allocated by `ExtractData`.
This fix captures the actual number of elements extracted by
`ExtractData` and uses this value for the output allocation and loop
iteration, ensuring memory safety when vertex remapping is active.
Verified with ASan and existing unit tests.
Added a comprehensive AI Tool Use Policy outlining guidelines for contributors on using AI tools, ensuring human oversight and accountability in contributions.
- closes https://github.com/assimp/assimp/issues/6538
fix(gltf2): preserve interpolation type and CubicSpline tangents
The glTF2 importer previously ignored the mInterpolation field and discarded
CubicSpline tangent data, leading to incorrect animation playback.
- Implement MapInterpolation() to map glTF2 interpolation types to Assimp.
- Set mInterpolation for all aiVectorKey and aiQuatKey instances.
- For CUBICSPLINE samplers, store [in-tangent, value, out-tangent] triplets
(N x 3 keys) instead of discarding tangents.
- Fixes rendering consistency for InterpolationTest.glb where STEP, LINEAR,
and CUBICSPLINE rows previously rendered identically.
Affected channels: mPositionKeys, mRotationKeys, mScalingKeys.
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
* Update supported version in SECURITY.md
- Preparation for bugfix release v6.0.5
* Update CMakeLists.txt
* Update aiGetVersionPatch test to expect version 5
In `HL1MDLLoader::read_animations`, the arrays for `scene_->mAnimations`
and `scene_animation->mChannels` were allocated using `new T*[count]`.
This performs default initialization, which leaves the pointer elements
with indeterminate (garbage) values.
If an exception (such as a `DeadlyImportError` from malformed input) is
thrown during the loop populating these arrays, the `aiScene` or
`aiAnimation` destructors are invoked during stack unwinding. These
destructors iterate through the allocated arrays and call `delete` on
each element. Because the arrays contained garbage values for indices
not yet reached by the loader, the destructor attempted to delete
invalid memory addresses, leading to a segmentation fault.
This patch changes the allocations to use value-initialization (`new
T*[count]()`), ensuring all pointers are initialized to `nullptr`. Since
`delete nullptr` is a safe no-op, the destructors can now safely clean
up partially initialized objects during an exception.
Fixes: https://issues.oss-fuzz.com/issues/483188619
Co-authored-by: CodeMender <codemender-patching@google.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
The `ObjFileParser::getFace` method failed to recognize the vertical tab
character (`\v`, 0x0b) as a separator. While the `IsSpaceOrNewLine`
utility handles most whitespace (space, tab, CR, LF, FF), it excludes
`\v`.
When encountering a vertical tab, the parser fell through to an `else`
block that calls `::atoi(&(*m_DataIt))`. Because `atoi` treats `\v` as
whitespace per the C standard, it skips the character and continues
reading. If `\v` is located at the end of the buffer (e.g., followed by
a newline at the buffer boundary), `atoi` can read past the allocated
memory, triggering a heap-buffer-overflow.
This fix explicitly checks for `\v` and treats it as a separator,
resetting the position counter and preventing the invalid `atoi` call.
Verified with AddressSanitizer and confirmed that all 584 existing unit
tests pass.
Fixes: https://issues.oss-fuzz.com/issues/476180586
Signed-off-by: Bill Wendling <morbo@google.com>
Co-authored-by: Meder Kydyraliev <meder@google.com>
Co-authored-by: CodeMender <codemender-patching@google.com>
The FBX exporter was unconditionally dereferencing a map iterator (`tp_elem`)
even when the key was not found (i.e., `tp_elem == tpath_by_image.end()`).
This resulted in a stack-use-after-scope error when accessing `tp_elem->second`
to populate "FileName" and "RelativeFilename" nodes, as dereferencing the
end iterator of the map accessed invalid stack memory (the map's sentinel).
The code already correctly initialized a local `tfile_path` variable based
on whether the iterator was valid. This patch updates the `AddChild` calls
to use `tfile_path` instead of dereferencing the potentially invalid iterator.
Fixes: https://issues.oss-fuzz.com/issues/465494996
Co-authored-by: CodeMender <codemender-patching@google.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
* glTF2: Fix heap-buffer-overflow in Accessor validation and size calculation
This patch fixes a heap-buffer-overflow in
`glTF2::Accessor::ExtractData` caused by incorrect bounds validation and
available size reporting.
The vulnerability stemmed from two issues in `glTF2Asset.inl`:
1. **Underestimated validation in `Accessor::Read`**: The logic used
`GetBytesPerComponent() * count` to validate the required buffer
size. This failed to account for the actual `stride`, allowing
accessors to pass validation even if their total footprint
(including stride) exceeded the buffer view.
2. **Incorrect size reporting in `Accessor::GetMaxByteSize`**: The
function returned the total `bufferView->byteLength` while ignoring
the `byteOffset`. Since the accessor data starts at `byteOffset`,
the actual available space is `byteLength - byteOffset`. This led
`ExtractData` to permit reads that extended beyond the end of the
allocated buffer.
Changes:
* Modified `Accessor::Read` to use `GetStride() * count` for length
validation.
* Updated `Accessor::GetMaxByteSize` to correctly return
`bufferView->byteLength - byteOffset` for standard accessors and
`sparse->data.size()` for sparse accessors.
Co-authored-by: CodeMender <codemender-patching@google.com>
Fixes: https://issues.oss-fuzz.com/issues/483102963
* address comment
---------
Co-authored-by: CodeMender <codemender-patching@google.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
The mColors[0] array was allocated with m_numColors elements but
indexed up to mNumVertices (= numFaces * 3), causing an out-of-bounds
write when the color count is less than the vertex count.
Allocate mColors[0] with mNumVertices (matching mNormals and
mTextureCoords), and add a bounds check on idx before reading
from the source color array.
Fixes#6468
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
* Add developer quickstart section to Readme
-Added a quickstart guide for developers to clone and build the project.
- closes https://github.com/assimp/assimp/issues/6469
* Change headings from H3 to H2 in Readme.md
Add buffer boundary checks before reading frame data to prevent out-of-bounds reads on malformed MDL files.
Fixes#6172 (CVE-2025-5200)
Signed-off-by: mapengyuan <mapengyuan@xfusion.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
Add validations check in AC3DImporter::ConvertObjectSection to ensure that writing TriangleStrip vertex data does not exceed mesh->mNumVertices allocation.
Fixes#6015 (CVE-2025-2754)
Fixes#6018 (CVE-2025-2756)
Signed-off-by: mapengyuan <mapengyuan@xfusion.com>
* Update copyright year and project version
- Fixes version in lib
* Update copyright year to 2026
* Update copyright year to 2026 in Version.cpp
* Update copyright year and version patch test
* Fix copyright year
* Adapt copyrights
* Fix some recently implemented comparisons of token strings. Previously, the `keyword` included the following space along with the token, which broke the string comparison using the equality operator.
* Rename `getEndOfToken` -> `getNextDelimiter`, to reflect the actual usage
Improve bounds checks in MD3Importer::ValidateSurfaceHeaderOffsets to prevent pcSurf from accessing data outside the MD3 buffer (fixes#6070, CVE-2025-3549).
Signed-off-by: mapengyuan <mapengyuan@xfusion.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
- Validate ulOffsetEnd in MDCImporter::ValidateSurfaceHeader to
prevent pcSurface2 from moving past the MDC buffer(fixes#6167, CVE-2025-5165).
- Apply AI_SWAP4 to ulOffsetShaders before using it in bounds checks.
Signed-off-by: mapengyuan <mapengyuan@xfusion.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
A segmentation fault occurred while parsing an MD5 file that contains an invalid vertex index.
The issue was caused by mScene->mMaterials not being kept in sync with mScene->mNumMaterials.
As a result, the aiScene destructor could call delete on uninitialized pointers. This patch
ensures that mScene->mNumMaterials always matches the actual contents of the mScene->mMaterials
array. That way, if an exception is thrown during file import, delete is only called for
properly allocated aiMaterial objects.
The ForceFormat function unregisters importers from the Importer
but doesn't delete them, causing memory leaks detected by ASan
during OSS-Fuzz check_build.
When UnregisterLoader is called, the importer is removed from the
internal list but the memory is not freed. Since the Importer
originally allocated these objects and we're removing them from
its management, we must delete them explicitly.
Also include BaseImporter.h to ensure complete type information
is available for proper deletion.
This fixes OSS-Fuzz check_build failures for all format-specific
fuzzers (obj, gltf, glb, fbx, collada, stl).