Skip to content

[rmodels] Build failure in 'LoadIQM' on GCC 16.1 #5950

Description

@eloj

Issue description

The IQM object loader code is assigning an unsigned int from iqmHeader->num_joints to boneCount in struct ModelSkeleton, which is an int. The compiler detects that this can potentially overflow into a negative value, which is then passed to the allocator as a size_t potentially resulting in a huge allocation.

Tested at bb96b92

The Error

[ 36%] Linking C executable models_orthographic_projection
In function 'LoadIQM',
    inlined from 'LoadModel.constprop' at /home/eddy/dev/EXT/raylib/src/rmodels.c:1110:52:
/home/eddy/dev/EXT/raylib/src/rmodels.c:5014:38: error: argument 1 range [18446744071562067968, 18446744073709551615] exceeds maximum object size 9223372036854775807 [-Werror=alloc-size-larger-than=]
 5014 |     model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
      |                                      ^
/usr/include/stdlib.h: In function 'LoadModel.constprop':
/usr/include/stdlib.h:675:14: note: in a call to allocation function 'calloc' declared here
  675 | extern void *calloc (size_t __nmemb, size_t __size)
      |              ^
In function 'LoadIQM',
    inlined from 'LoadModel.constprop' at /home/eddy/dev/EXT/raylib/src/rmodels.c:1110:52:
/home/eddy/dev/EXT/raylib/src/rmodels.c:5015:36: error: argument 1 range [18446744071562067968, 18446744073709551615] exceeds maximum object size 9223372036854775807 [-Werror=alloc-size-larger-than=]
 5015 |     model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
      |                                    ^
/usr/include/stdlib.h: In function 'LoadModel.constprop':
/usr/include/stdlib.h:675:14: note: in a call to allocation function 'calloc' declared here
  675 | extern void *calloc (size_t __nmemb, size_t __size)
      |              ^
In function 'LoadIQM',
    inlined from 'LoadModel.constprop' at /home/eddy/dev/EXT/raylib/src/rmodels.c:1110:52:
/home/eddy/dev/EXT/raylib/src/rmodels.c:5014:38: error: argument 1 range [18446744071562067968, 18446744073709551615] exceeds maximum object size 9223372036854775807 [-Werror=alloc-size-larger-than=]
 5014 |     model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
      |                                      ^
/usr/include/stdlib.h: In function 'LoadModel.constprop':
/usr/include/stdlib.h:675:14: note: in a call to allocation function 'calloc' declared here
  675 | extern void *calloc (size_t __nmemb, size_t __size)
      |              ^
In function 'LoadIQM',
    inlined from 'LoadModel.constprop' at /home/eddy/dev/EXT/raylib/src/rmodels.c:1110:52:
/home/eddy/dev/EXT/raylib/src/rmodels.c:5015:36: error: argument 1 range [18446744071562067968, 18446744073709551615] exceeds maximum object size 9223372036854775807 [-Werror=alloc-size-larger-than=]
 5015 |     model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
      |                                    ^
/usr/include/stdlib.h: In function 'LoadModel.constprop':
/usr/include/stdlib.h:675:14: note: in a call to allocation function 'calloc' declared here
  675 | extern void *calloc (size_t __nmemb, size_t __size)
      |              ^
lto1: all warnings being treated as errors
make[3]: *** [/tmp/ccsbdewr.mk:14: /tmp/cc7nxShc.ltrans6.ltrans.o] Error 1

Build

This is my build command:

EXTRA_CFLAGS="-flto=auto -fuse-linker-plugin"
cmake -DCMAKE_C_FLAGS="-march=native -mtune=native -Werror ${EXTRA_CFLAGS}" -DCMAKE_INSTALL_PREFIX=${PREFIX} \
	-DCMAKE_BUILD_TYPE=RelWithDebInfo \
	-DUSE_EXTERNAL_GLFW=ON -DGLFW_BUILD_WAYLAND=OFF \
	-S $HOME/dev/EXT/raylib -B build

The fix

Proposed minimum fix:

diff --git a/src/rmodels.c b/src/rmodels.c
index 28fb3c9ec..bde056186 100644
--- a/src/rmodels.c
+++ b/src/rmodels.c
@@ -4981,7 +4981,7 @@ static Model LoadIQM(const char *fileName)
     //fread(ijoint, sizeof(IQMJoint), iqmHeader->num_joints, iqmFile);
     memcpy(ijoint, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
 
-    model.skeleton.boneCount = iqmHeader->num_joints;
+    model.skeleton.boneCount = iqmHeader->num_joints & INT_MAX;
     model.skeleton.bones = (BoneInfo *)RL_CALLOC(iqmHeader->num_joints, sizeof(BoneInfo));
     model.skeleton.bindPose = (Transform *)RL_CALLOC(iqmHeader->num_joints, sizeof(Transform));

Obviously a more holistic fix would also adjust the local allocations to use the capped value, but I doubt any real/non-adversarial model would ever be affected by the mask to begin with.

Workaround

Setting SUPPORT_FILEFORMAT_IQM to zero in the configuration allows the build to proceed successfully.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions