Skip to content

[BUG] MessagePack negative fixint values decoded incorrectly #368

@MarkLee131

Description

@MarkLee131

The msgpack negative fixint decoder in src/ucl_msgpack.c:1389 uses a wrong bit mask, so every negative fixint value (-1 through -32) comes out wrong. For example, byte 0xff should decode to -1 but gives -31 instead. This affects all versions up to and including 0.9.4. (CWE-681).

Specifically, the bit mask is just incorrect:

// ucl_msgpack.c:1388-1390
case msgpack_negative_fixint:
    obj->value.iv = -(*pos & 0x1f);
    len = 1;

Per the MessagePack specification, negative fixint stores values in the range [-32, -1] directly as a signed 8-bit integer in bytes 0xe0 through 0xff. The correct decoding is simply (int8_t)*pos.

The current mask 0x1f extracts only the low 5 bits and negates them, producing a completely inverted mapping:

Byte Expected Actual
0xe0 -32 0
0xe1 -31 -1
0xfe -2 -30
0xff -1 -31

Every negative fixint value in every msgpack input parsed by libucl is silently corrupted.

Reproduction

#include <stdio.h>
#include <ucl.h>

int main(void) {
    /* fixmap(1){ fixstr(1)"a" : negative_fixint(0xff = should be -1) } */
    unsigned char data[] = {0x81, 0xa1, 0x61, 0xff};

    struct ucl_parser *p = ucl_parser_new(0);
    ucl_parser_add_chunk_full(p, data, 4, 0, UCL_DUPLICATE_APPEND, UCL_PARSE_MSGPACK);
    ucl_object_t *obj = ucl_parser_get_object(p);

    const ucl_object_t *val = ucl_object_lookup(obj, "a");
    printf("0xff: got %lld, expected -1\n", (long long)ucl_object_toint(val));
    /* Output: 0xff: got -31, expected -1 */

    ucl_object_unref(obj);
    ucl_parser_free(p);
    return 0;
}

Suggested Fix

Replace the incorrect mask with a direct signed cast:

case msgpack_negative_fixint:
    obj->value.iv = (int8_t)*pos;
    len = 1;
    break;

Happy to send a PR if that helps. :)

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