raygui icon indicating copy to clipboard operation
raygui copied to clipboard

`GuiValueBoxFloat()` has `*textValue` argument and modifies it.

Open nezvers opened this issue 7 months ago • 1 comments

What's going here? https://github.com/raysan5/raygui/blob/0895c8b8c4bf9e111492b19fba336d62d4a0b960/src/raygui.h#L3140 If comparing to GuiValueBox it has member variable char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] with predefined size. But GuiValueBox takes it in as an argument and modifies it. If I'm leaving it blank with "" it kinda works. It is manipulating text argument by showing value, except lost first symbol. Seems like a stack overflow.

nezvers avatar Apr 20 '25 14:04 nezvers

@nezvers GuiValueBoxFloat() was contributed a while ago and has some additional restrictions, it could require more testing or review...

raysan5 avatar May 06 '25 20:05 raysan5

I had some time to review the current implementation of GuiValueBoxFloat(), and I think I found out why it requires a char *textValue parameter.

The user input (textValue) from GuiValueBoxFloat() should not be converted to a float value until the user finishes typing (e.g. by pressing the KEY_ENTER key or the KEY_KP_ENTER key).

For example, let's say GuiValueBoxFloat() does not have the textValue parameter, and instead, it has a function definition similar to GuiValueBox():

int GuiValueBoxFloat(Rectangle bounds, const char *text, float *value, int minValue, int maxValue, bool editMode)
{
    #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
        #define RAYGUI_VALUEBOX_MAX_CHARS  32
    #endif

    int result = 0;
    GuiState state = guiState;

    char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
    snprintf(textValue, sizeof(textValue), "%f", *value);

    /* ... */
}

If *value contains 0.0f, then the control would show 0.000000. As we press the KEY_BACKSPACE key to delete a character from 0.000000, textValue now contains "0.00000", and *value contains TextToFloat("0.00000") = 0.0f. This means even if we try to delete a character, we won't be able to do it because textValue will always contain the same string for every function call.

The similar happens when the user tries to type a digit character (from '0' to '9'). As we press the 1 key, textValue now contains 0.0000001, and *value contains TextToFloat("0.0000001") = 0.0000001f. However, during the next function call of GuiValueBoxFloat(), snprintf() will convert "0.0000001" to "0.000000", because the %f format specifier can only display 6 digits as the fractional part.

The conclusion is, we need a way for textValue not to be converted to an actual float value until the user finishes typing, and the current implementation of GuiValueBoxFloat() seems to be doing this by using the textValue parameter.

jdeokkim avatar Jun 24 '25 08:06 jdeokkim