[vlc-devel] [PATCH] check for crazy values in rtsp npt range

Tobias Güntner fatbull at web.de
Fri Mar 30 00:35:54 CEST 2012


Am 25.03.2012 09:21, schrieb Tobias Güntner:
> * Perhaps checking if a value >= INT64_MAX (instead of > INT64_MAX) is
> sufficient?

I'm reasonably sure this will work.

* If INT64_MAX is rounded towards infinity, it is rounded to the nearest 
representable value, i.e., there is no double between the actual 
INT64_MAX and (double)INT64_MAX. Therefore (double)INT64_MAX is the very 
first "invalid" value which must be replaced.

* If INT64_MAX has an exact representation, replacing INT64_MAX with 
INT64_MAX is obviously correct. ;)

* If INT64_MAX is rounded towards zero (and I doubt this will ever 
happen in practice), the rounded double value is still within INT64 
limits, i.e., the cast is safe.

(Analogously for INT64_MIN, INT32_MIN/MAX, etc.)

I attached a patch and a separate test program (because it was easier to 
test this way).

Regards,
Tobias
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Improve-range-check.patch
Type: text/x-patch
Size: 1078 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20120330/be2774bc/attachment.bin>
-------------- next part --------------
#undef NDEBUG
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <fenv.h>
#include <assert.h>
#include <float.h>

/** Safely truncates floating point values to integers */
int64_t vlc_trunc64( double value )
{
    /* Use >= instead of > because INT64_MAX could be rounded
     * up when converted to a double for comparison. */
    if( value >= INT64_MAX )
        return INT64_MAX;
    else if( value <= INT64_MIN )
        return INT64_MIN;
    else if( isnan( value ) )
        return 0;
    else
        return (int64_t)value;
}

#if !defined(math_errhandling) || !( math_errhandling & MATH_ERREXCEPT )
#error This test requires floating point exceptions!
#endif

int64_t test_truncate( double value )
{
    feclearexcept( FE_ALL_EXCEPT );
    int64_t i = vlc_trunc64( value );
    int exc = fetestexcept( FE_ALL_EXCEPT );
    printf( "%f -> %"PRIi64" %i\n", value, i, exc );
    assert( ( exc & ~FE_INEXACT ) == 0 );
    return i;
}

#define testx( value, result ) \
    assert( test_truncate( value ) result )

#define test( value, result ) \
    testx( value, == ( result ) )

int main()
{
    double max = INT64_MAX;
    double min = INT64_MIN;

    /* make sure errors can be detected */
    feclearexcept( FE_ALL_EXCEPT );
    assert( !fetestexcept( FE_ALL_EXCEPT ) );
    int64_t i = (int64_t)( max - min );
    assert( fetestexcept( FE_INVALID ) );
    printf( "%"PRIi64"\n", i );

    assert( +DBL_MAX > INT64_MAX );
    assert( -DBL_MAX < INT64_MIN );

    test( +INFINITY, INT64_MAX );
    test( -INFINITY, INT64_MIN );

    test( +HUGE_VAL, INT64_MAX );
    test( -HUGE_VAL, INT64_MIN );

    test( max * 2, INT64_MAX );
    test( min * 2, INT64_MIN );

    test( nextafter( max, +INFINITY ), INT64_MAX );
    test( nextafter( min, -INFINITY ), INT64_MIN );
    
    test( max, INT64_MAX );
    test( min, INT64_MIN );

    testx( nextafter( max, 0 ), < INT64_MAX );
    testx( nextafter( min, 0 ), > INT64_MIN );

    test( +INT64_C(0x4000000000000000), +INT64_C(0x4000000000000000) );
    test( -INT64_C(0x4000000000000000), -INT64_C(0x4000000000000000) );

    test( +123.456, +123 );
    test( -123.456, -123 );

    test( +0.999999, 0 );
    test( -0.999999, 0 );

    test( +0.0, 0 );
    test( -0.0, 0 );

    test( +NAN, 0 );
    test( -NAN, 0 );

    printf("OK!\n");
    return 0;
}


More information about the vlc-devel mailing list