Skip to content

[rtextures.c] ColorToInt(RED) is UB #3987

Closed
@OetkenPurveyorOfCode

Description

@OetkenPurveyorOfCode

Minimal example:

#include "raylib.h"

int main(void)
{
    ColorToInt(RED);
    return 0;
}

Produces the following error:

../raylib/src\rtextures.c:4513:33: runtime error: left shift of 230 by 24 places cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../raylib/src\rtextures.c:4513:33 in

The issue is that any color with a high enough RED value causes the signed integer to overflow which is undefined as per the C standard.

This happens here:

int ColorToInt(Color color)
{
    int result = (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);

    return result;
}

I tired rewriting it either to:

int ColorToInt(Color color)
{
    unsigned int unsinged_result = (((unsigned int)color.r << 24) | ((unsigned int)color.g << 16) | ((unsigned int)color.b << 8) | (unsigned int)color.a);
    int result;
    memcpy(&result, &unsigned_result, 4);
    return result;
}

which assumes that int is 4 bytes and stored as two's complement. (That would be UB on another machine but that does not affect me, the signed overflow affects me though)

Or this ugly dance around (https://stackoverflow.com/questions/5129498/how-to-cast-or-convert-an-unsigned-int-to-int-in-c):

        int result;
        if (unsigned_result < INT_MAX) {
            result = unsigned_result;
        }
        else {
            result = -(unsigned int)(~unsigend_result) -1;
        }

(which also assume 2's complement which is only guaranteed in the latest C standard (but I am compiling with -std=c2x, so that would not be an issue for bleeding edge people like me)

Both run fine without triggering UBSAN for the entire range of uints (though retyping them in this issue may have introduced errors)

Or should the ColorToInt signature to be changed to return an unsigned int (probably a breaking change)?

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