Commit 1ec6ffa7 authored by malenov's avatar malenov
Browse files

enable safety checks of indices during bitstream writing

parent 00a01e81
Loading
Loading
Loading
Loading
Loading
+224 −4
Original line number Diff line number Diff line
@@ -50,7 +50,9 @@
#include "wmc_auto.h"
#include "ivas_prot_fx.h"
#include "prot_fx_enc.h"

#ifdef DEBUGGING
#include "debug.h"
#endif

#define STEP_MAX_NUM_INDICES 100 /* increase the maximum number of allowed indices in the list by this amount */

@@ -843,6 +845,9 @@ ivas_error check_ind_list_limits(
    /* the re-allocation can be avoided by increasing the limits in get_ivas_max_num_indices() or get_ivas_max_num_indices_metadata() */
    IF( GE_16( (Word16) ( &hBstr->ind_list[hBstr->nb_ind_tot] - ivas_ind_list_zero ), *( hBstr->ivas_max_num_indices ) ) )
    {
#ifdef DEBUGGING
        fprintf( stderr, "Warning: The maximum number of indices %d has been exceeded in frame %d! Increase the limits in get_ivas_max_num_indices() or get_max_num_indices_metadata().\n", *( hBstr->ivas_max_num_indices ), frame );
#endif

        /* reallocate the buffer of indices with increased limit */
        IF( NE_32( ( error = ind_list_realloc( *hBstr->ivas_ind_list_zero, *( hBstr->ivas_max_num_indices ) + STEP_MAX_NUM_INDICES, hBstr->st_ivas ) ), IVAS_ERR_OK ) )
@@ -856,6 +861,10 @@ ivas_error check_ind_list_limits(
    {
        IF( hBstr->nb_ind_tot == 0 )
        {
#ifdef DEBUGGING
            fprintf( stderr, "Warning: Trying to overwrite an existing indice ID = %d in frame %d!\n", hBstr->ind_list[hBstr->nb_ind_tot].id, frame );
#endif

            /* move the pointer to the next available empty slot */
            ivas_ind_list_last = &ivas_ind_list_zero[*( hBstr->ivas_max_num_indices )];
            WHILE( hBstr->ind_list[0].nb_bits > 0 && hBstr->ind_list < ivas_ind_list_last )
@@ -865,6 +874,9 @@ ivas_error check_ind_list_limits(

            IF( hBstr->ind_list >= ivas_ind_list_last )
            {
#ifdef DEBUGGING
                fprintf( stderr, "Warning: The maximum number of indices %d has been exceeded in frame %d! Increase the limits in get_ivas_max_num_indices() or get_max_num_indices_metadata().\n", *( hBstr->ivas_max_num_indices ), frame );
#endif

                /* no available empty slot -> need to re-allocate the buffer */
                IF( NE_32( ( error = ind_list_realloc( *hBstr->ivas_ind_list_zero, *( hBstr->ivas_max_num_indices ) + STEP_MAX_NUM_INDICES, hBstr->st_ivas ) ), IVAS_ERR_OK ) )
@@ -875,7 +887,11 @@ ivas_error check_ind_list_limits(
        }
        ELSE
        {
#ifdef DEBUGGING
            return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Buffer of indices corrupted in frame %d! Attempt to overwrite indice ID = %d (value: %d, bits: %d)!\n", frame, hBstr->ind_list[hBstr->nb_ind_tot].id, hBstr->ind_list[hBstr->nb_ind_tot].value, hBstr->ind_list[hBstr->nb_ind_tot].nb_bits );
#else
            return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Buffer of indices corrupted in frame %d! Attempt to overwrite indice ID = %d (value: %d, bits: %d)!\n", hBstr->ind_list[hBstr->nb_ind_tot].id, hBstr->ind_list[hBstr->nb_ind_tot].value, hBstr->ind_list[hBstr->nb_ind_tot].nb_bits );
#endif
        }
    }

@@ -903,10 +919,26 @@ ivas_error push_indice(
    error = IVAS_ERR_OK;
    move32();

#ifdef DEBUGGING
    if ( nb_bits < ( 32 - 1 ) && ( value >> nb_bits ) > 0 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice ID = %d with value %d exceeds the range of %d bits (frame %d) !\n", id, value, nb_bits, frame );
    }

    if ( nb_bits > 16 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice ID = %d with value %d is trying to allocate %d bits which exceeds 16 bits (frame %d) !\n", id, value, nb_bits, frame );
    }
#endif

    /* check the limits of the list of indices */
    IF( NE_32( ( error = check_ind_list_limits( hBstr ) ), IVAS_ERR_OK ) )
    {
        return IVAS_ERROR( error, "Error occured in push_indice() while re-allocating the list of indices (frame %d) !\n" );
#ifdef DEBUGGING
        return IVAS_ERROR( error, "Error occured in push_indice() while re-allocating the list of indices (frame %d) !\n", frame );
#else
        return IVAS_ERROR( error, "Error occured in push_indice() while re-allocating the list of indices!\n" );
#endif
    }

    /* find the location in the list of indices based on ID */
@@ -968,6 +1000,17 @@ ivas_error push_next_indice(
    error = IVAS_ERR_OK;
    move32();

#ifdef DEBUGGING
    if ( nb_bits < ( 32 - 1 ) && ( value >> nb_bits ) > 0 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice with value %d exceeds the range of %d bits (frame %d) !\n", value, nb_bits, frame );
    }

    if ( nb_bits > 16 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice with value %d is trying to allocate %d bits which exceeds 16 bits !\n", value, nb_bits );
    }
#endif

    /* check the limits of the list of indices */
    IF( NE_32( ( error = check_ind_list_limits( hBstr ) ), IVAS_ERR_OK ) )
@@ -1044,7 +1087,11 @@ ivas_error push_next_bits(
        /* check the limits of the list of indices */
        IF( NE_32( ( error = check_ind_list_limits( hBstr ) ), IVAS_ERR_OK ) )
        {
            return IVAS_ERROR( error, "Error occured in push_next_bits() while re-allocating the list of indices (frame %d) !\n" );
#ifdef DEBUGGING
            return IVAS_ERROR( error, "Error occured in push_next_bits() while re-allocating the list of indices (frame %d) !\n", frame );
#else
            return IVAS_ERROR( error, "Error occured in push_next_bits() while re-allocating the list of indices!\n" );
#endif
        }
        ptr = &hBstr->ind_list[hBstr->nb_ind_tot];

@@ -1065,7 +1112,11 @@ ivas_error push_next_bits(
        /* check the limits of the list of indices */
        IF( NE_32( ( error = check_ind_list_limits( hBstr ) ), IVAS_ERR_OK ) )
        {
            return IVAS_ERROR( error, "Error occured in push_next_bits() while re-allocating the list of indices (frame %d) !\n" );
#ifdef DEBUGGING
            return IVAS_ERROR( error, "Error occured in push_next_bits() while re-allocating the list of indices (frame %d) !\n", frame );
#else
            return IVAS_ERROR( error, "Error occured in push_next_bits() while re-allocating the list of indices!\n" );
#endif
        }
        ptr = &hBstr->ind_list[hBstr->nb_ind_tot];

@@ -1374,6 +1425,9 @@ static Word16 write_indices_to_stream_fx(
    Word16 i, k;
    Word16 value, nb_bits;
    UWord16 mask;
#ifdef ENABLE_BITRATE_VERIFICATION
    int16_t total_nb_bits = 0;
#endif

    FOR( i = 0; i < num_indices; i++ )
    {
@@ -1384,6 +1438,9 @@ static Word16 write_indices_to_stream_fx(

        IF( nb_bits > 0 )
        {
#ifdef ENABLE_BITRATE_VERIFICATION
            total_nb_bits += nb_bits;
#endif
            /* mask from MSB to LSB */
            mask = (UWord16) L_shl( 1, sub( nb_bits, 1 ) );

@@ -1406,8 +1463,22 @@ static Word16 write_indices_to_stream_fx(
                mask = (UWord16) L_shr( mask, 1 );
            }
        }
#ifdef DEBUGGING
        else if ( nb_bits == 0 )
        {
            /* fprintf( stderr, "Warning: %s: nb_bits == 0!\n", __func__ ); */
        }
        else
        {
            /* fprintf( stderr, "Warning: %s: nb_bits == %d!\n", __func__, nb_bits ); */
        }
#endif
    }
#ifdef ENABLE_BITRATE_VERIFICATION
    return total_nb_bits;
#else
    return 0;
#endif 
}

/*-------------------------------------------------------------------*
@@ -1432,6 +1503,9 @@ static ivas_error write_indices_element_fx(

    Indice *ind_list_metadata;
    Word16 n, n_channels;
#ifdef ENABLE_BITRATE_VERIFICATION
    int16_t total_nb_bits;
#endif
    ivas_error error;

    error = IVAS_ERR_OK;
@@ -1479,6 +1553,12 @@ static ivas_error write_indices_element_fx(
                move16();
            }
        }
#ifdef DEBUGGING
        else
        {
            return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Bitstream writing error in frame %d. Exiting!\n", frame );
        }
#endif
    }

    n_channels = 1;
@@ -1511,15 +1591,35 @@ static ivas_error write_indices_element_fx(
            pt_stream_loc += nb_bits_tot_metadata - 1;
            pt_stream_end = pt_stream_loc + 1;

#ifdef ENABLE_BITRATE_VERIFICATION
            total_nb_bits =
#endif
            write_indices_to_stream_fx( ind_list_metadata, &pt_stream_loc, -1,
                                        nb_ind_tot_metadata );

#ifdef ENABLE_BITRATE_VERIFICATION
            if ( total_nb_bits != nb_bits_tot_metadata )
            {
                return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Bitstream write size mismatch! Written bits: %d vs. Reference bits: %d\n", total_nb_bits, nb_bits_tot_metadata );
            }
#endif
            /* restore previous pointer position */
            pt_stream_loc = pt_stream_backup;
        }

#ifdef ENABLE_BITRATE_VERIFICATION
        total_nb_bits =
#endif
        write_indices_to_stream_fx( sts[n]->hBstr->ind_list, &pt_stream_loc, 1,
                                    sts[n]->hBstr->nb_ind_tot );

#ifdef ENABLE_BITRATE_VERIFICATION
        if ( total_nb_bits != sts[n]->hBstr->nb_bits_tot )
        {
            return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Bitstream write size mismatch! Written bits: %d vs. Reference bits: %d\n", total_nb_bits, sts[n]->hBstr->nb_bits_tot );
        }
#endif

        if ( pt_stream_loc > pt_stream_end )
        {
            pt_stream_end = pt_stream_loc;
@@ -1574,6 +1674,11 @@ ivas_error write_indices_ivas_fx(
    Word16 i, n;
    UWord16 *pt_stream;
    ivas_error error;
#ifdef ENABLE_BITRATE_VERIFICATION
    Encoder_State **sts;
    int32_t ivas_total_brate;
    int16_t ch;
#endif

    error = IVAS_ERR_OK;
    move32();
@@ -1585,6 +1690,45 @@ ivas_error write_indices_ivas_fx(
        move16();
    }

#ifdef ENABLE_BITRATE_VERIFICATION
    i = 0;

    for ( n = 0; n < st_ivas->nSCE; n++ )
    {
        sts = st_ivas->hSCE[n]->hCoreCoder;
        i += sts[0]->hBstr->nb_bits_tot;

        if ( st_ivas->hSCE[n]->hMetaData != NULL )
        {
            i += st_ivas->hSCE[n]->hMetaData->nb_bits_tot;
        }
    }

    for ( n = 0; n < st_ivas->nCPE; n++ )
    {
        sts = st_ivas->hCPE[n]->hCoreCoder;
        for ( ch = 0; ch < CPE_CHANNELS; ch++ )
        {
            i += sts[ch]->hBstr->nb_bits_tot;
        }

        if ( st_ivas->hCPE[n]->hMetaData != NULL )
        {
            i += st_ivas->hCPE[n]->hMetaData->nb_bits_tot;
        }
    }

    ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
    if ( st_ivas->hEncoderConfig->Opt_SC_VBR )
    {
        ivas_total_brate = st_ivas->hSCE[0]->hCoreCoder[0]->total_brate;
    }

    if ( i * FRAMES_PER_SEC != ivas_total_brate && i >= ACELP_11k60 / FRAMES_PER_SEC )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Bitstream write size mismatch! Actual bitrate: %ld vs. Reference bitrate: %d\n", i * 50L, ivas_total_brate );
    }
#endif

    /*-----------------------------------------------------------------*
     * Encode Payload
@@ -1650,6 +1794,9 @@ static void decoder_selectCodec(
                    st->codec_mode = MODE1;
                    break;
                default: /* validate that total_brate (derived from RTP packet or a file header) is one of the defined bitrates  */
#ifdef DEBUGGING
                    IVAS_ERROR( IVAS_ERR_INTERNAL, "Error illegal total bitrate (= %d) \n", total_brate );
#endif
                    st->codec_mode = st->last_codec_mode;
                    st->bfi = 1;
                    break;
@@ -1722,6 +1869,12 @@ static void dec_prm_core(
            }
        }

#ifdef DEBUGGING
        if ( n == FRAME_SIZE_NB )
        {
            assert( !"Bitrate not supported: not part of EVS" );
        }
#endif
        /* Get audio bandwidth info */
        st->bwidth = get_next_indice( st, FrameSizeConfig[frame_size_index].bandwidth_bits );
        st->bwidth += FrameSizeConfig[frame_size_index].bandwidth_min;
@@ -1819,6 +1972,9 @@ static void decision_matrix_core_dec(
        while ( acelp_sig_tbl[start_idx] != st->total_brate )
        {
            start_idx++;
#ifdef DEBUGGING
            assert( ( start_idx < 194 ) && "ERROR: start_idx larger than acelp_sig_tbl[].\n" );
#endif
        }

        /* skip the bitrate */
@@ -1964,6 +2120,57 @@ void mdct_switching_dec(
    return;
}

#ifdef DEBUGGING
/*-------------------------------------------------------------------*
 * file_read_FECpattern()
 *
 * Simulate packet losses by reading FEC pattern from external file
 *-------------------------------------------------------------------*/

static ivas_error file_read_FECpattern(
    int16_t *bfi )
{
    ivas_error error;

    error = IVAS_ERR_OK;
    *bfi = 0;

    /* FEC pattern file provided */
    if ( FEC_pattern != NULL )
    {
        int16_t tmp = 0;
        if ( fread( &tmp, sizeof( int16_t ), 1, FEC_pattern ) != 1 )
        {
            if ( feof( FEC_pattern ) != 0 )
            {
#ifdef WRAP_AS_EIDXOR
                fseek( FEC_pattern, 0L, SEEK_SET );
                fread( &tmp, sizeof( int16_t ), 1, FEC_pattern );
#else
                tmp = 0;
                fseek( FEC_pattern, 0L, SEEK_SET );
#endif
            }
            else
            {
                return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error reading the FEC pattern file !" );
            }
        }

        if ( tmp == 2609 || tmp == 1 || tmp == (uint16_t) 0x6B20 /* == G192_SYNC_BAD_FRAME */ )
        {
            *bfi = 1;
        }
        else
        {
            *bfi = 0;
        }
    }

    return error;
}
#endif


/*-------------------------------------------------------------------*
 * reset_elements()
@@ -2085,7 +2292,20 @@ ivas_error read_indices(
    st_ivas->num_bits = num_bits;
    sts = reset_elements( st_ivas );

#ifdef DEBUGGING
    file_read_FECpattern( &st_ivas->bfi );
    st_ivas->bfi |= bfi;

    if ( bfi == FRAMEMODE_MISSING )
    {
        for ( k = 0; k < num_bits; k++ )
        {
            bit_stream[k] = 0;
        }
    }
#else
    st_ivas->bfi = bfi;
#endif

    /* convert the frame length to total bitrate */
    total_brate = (int32_t) ( num_bits * FRAMES_PER_SEC );
+46 −0
Original line number Diff line number Diff line
@@ -44,6 +44,10 @@
#include "basop_util.h"
#include "rom_com.h"
#include "mime.h"
#ifdef DEBUGGING
#include "debug.h"
#endif


#ifdef DEBUGGING
/*-------------------------------------------------------------------*
@@ -268,7 +272,11 @@ Word16 rate2EVSmode(
 * Push a new indice into the buffer
 *-------------------------------------------------------------------*/

#ifdef DEBUGGING
ivas_error push_indice_fx(
#else
void push_indice_fx(
#endif
    BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
    Word16 id,             /* i  : ID of the indice */
    UWord16 value,         /* i  : value of the quantized indice */
@@ -277,6 +285,19 @@ void push_indice_fx(
{
    Word16 i;

#ifdef DEBUGGING
    ivas_error error = IVAS_ERR_OK;

    if ( nb_bits < ( 32 - 1 ) && ( value >> nb_bits ) > 0 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice ID = %d with value %d exceeds the range of %d bits (frame %d) !\n", id, value, nb_bits, frame );
    }

    if ( nb_bits > 16 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice ID = %d with value %d is trying to allocate %d bits which exceeds 16 bits (frame %d) !\n", id, value, nb_bits, frame );
    }
#endif

    IF( EQ_16( hBstr->last_ind_fx, id ) )
    {
@@ -309,7 +330,11 @@ void push_indice_fx(
    hBstr->nb_bits_tot = add( hBstr->nb_bits_tot, nb_bits );
    move16();

#ifdef DEBUGGING
    return error;
#else
    return;
#endif
}

/*-------------------------------------------------------------------*
@@ -317,12 +342,29 @@ void push_indice_fx(
 * Push a new indice into the buffer at the next position
 *-------------------------------------------------------------------*/

#ifdef DEBUGGING
ivas_error push_next_indice_fx(
#else
void push_next_indice_fx(
#endif
    BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
    UWord16 value,         /* i  : value of the quantized indice */
    Word16 nb_bits         /* i  : number of bits used to quantize the indice */
)
{
#ifdef DEBUGGING
    ivas_error error = IVAS_ERR_OK;

    if ( nb_bits < ( 32 - 1 ) && ( value >> nb_bits ) > 0 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice with value %d exceeds the range of %d bits (frame %d) !\n", value, nb_bits, frame );
    }

    if ( nb_bits > 16 )
    {
        return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Indice with value %d is trying to allocate %d bits which exceeds 16 bits !\n", value, nb_bits );
    }
#endif

    /* store the values in the list */
    hBstr->ind_list[hBstr->next_ind_fx].value = value;
@@ -336,7 +378,11 @@ void push_next_indice_fx(
    hBstr->nb_bits_tot = add( hBstr->nb_bits_tot, nb_bits );
    move16();

#ifdef DEBUGGING
    return error;
#else
    return;
#endif
}


+20 −0
Original line number Diff line number Diff line
@@ -63,11 +63,31 @@
 * If unexpected values are printed or the macro causes a crash, double check that the
 * format specifiers are correct.
 */
#ifdef DEBUGGING
#define IVAS_ERROR( error_code, ... ) ivas_error_wrapper( error_code, __func__, __FILE__, __LINE__, __VA_ARGS__ )
#else
#define IVAS_ERROR( error_code, ... ) ivas_error_wrapper( error_code )
#endif

#ifdef DEBUGGING
static inline ivas_error ivas_error_wrapper( const ivas_error error_code, const char *function, const char *file, int32_t line, const char *description, ... )
{
    fprintf( stderr, "\n%s: ", ivas_error_to_string( error_code ) );

    va_list args;
    va_start( args, description );
    vfprintf( stderr, description, args );
    va_end( args );

    fprintf( stderr, "\n\nIn function: %s(), %s:%d\n\n", function, file, line );

    return error_code;
}
#else
static inline ivas_error ivas_error_wrapper( const ivas_error error_code )
{
    return error_code;
}
#endif

#endif /* IVAS_ERROR_UTILS_H */
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@
#define DEBUG_MODE_INFO_TWEAK                 /* Enable command line switch to specify subdirectory for debug info output inside "./res/" */
#define DEBUG_FORCE_MDCT_STEREO_MODE      /* Force stereo mode decision for MDCT stereo: -stereo 3 1 forces L/R coding and -stereo 3 2 forces full M/S coding */
/*#define DBG_WAV_WRITER*/                    /* Enable dbgwrite_wav() function for generating ".wav" files */
#define ENABLE_BITRATE_VERIFICATION             /* Enable bitrate verification - use when playing with bit budget */
#endif

#define SUPPORT_JBM_TRACEFILE                   /* Support for JBM tracefile, which is needed for 3GPP objective/subjective testing, but not relevant for real-world implementations */
+8 −0
Original line number Diff line number Diff line
@@ -1168,14 +1168,22 @@ UWord16 get_next_indice_fx( /* o : value of the indice */
                            Word16 nb_bits        /* i  : number of bits that were used to quantize the indice */
);
#ifdef DEBUGGING
ivas_error push_indice_fx(
#else
void push_indice_fx(
#endif
    BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle       */
    Word16 id,             /* i  : ID of the indice */
    UWord16 value,         /* i  : value of the quantized indice */
    Word16 nb_bits         /* i  : number of bits used to quantize the indice */
);
#ifdef DEBUGGING
ivas_error push_next_indice_fx(
#else
void push_next_indice_fx(
#endif
    BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle       */
    UWord16 value,         /* i  : value of the quantized indice */
    Word16 nb_bits         /* i  : number of bits used to quantize the indice */