Skip to content

undefined behaviour in archive_read_support_format_mtree.c #539

Closed
@hannob

Description

@hannob

When compiling libarchive with the compile flag -fsanitize=undefined (enabling undefined behaviour sanitizer) it'll throw a warning when trying to open any mtree file:
libarchive/archive_read_support_format_mtree.c:146:10: runtime error: signed integer overflow: 9223372036854775807 * 2 cannot be represented in type 'long int'
libarchive/archive_read_support_format_mtree.c:168:6: runtime error: signed integer overflow: -9223372036854775808 * 2 cannot be represented in type 'long int'

This is the code that's causing this:
static int64_t
get_time_t_max(void)
{

if defined(TIME_T_MAX)

return TIME_T_MAX;

else

static time_t t;
time_t a;
if (t == 0) {
    a = 1;
    while (a > t) {
        t = a;
        a = a * 2 + 1;
    }
}
return t;

endif

}

static int64_t
get_time_t_min(void)
{

if defined(TIME_T_MIN)

return TIME_T_MIN;

else

/* 't' will hold the minimum value, which will be zero (if
 * time_t is unsigned) or -2^n (if time_t is signed). */
static int computed;
static time_t t;
time_t a;
if (computed == 0) {
    a = (time_t)-1;
    while (a < t) {
        t = a;
        a = a * 2;
    }           
    computed = 1;
}
return t;

endif

}

What libarchive is trying to do here is calculating the value of TIME_T_MIN/MAX by triggering an overflow.

However overflows in signed values are undefined in C. This code is therefore strictly speaking invalid, the compiler may do whatever it likes in such situations, without any defined outcome.

I haven't come up with an elegant other way to do this yet. Probably the best would be to convince the glibc devs to define TIME_T_MIN/MAX in their headers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions