Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51fb5e99 authored by Marco Nelissen's avatar Marco Nelissen
Browse files

Fix integer overflow in amrwbdec

The existing code did its own after-the-fact overflow checks.
Replace it with before-the-fact checks.

Bug: 28387859
Change-Id: Iea7e2055d0c0de54120b09a7a00df8a0a9192388
parent 35443e32
Loading
Loading
Loading
Loading
+46 −93
Original line number Diff line number Diff line
@@ -206,16 +206,18 @@ extern "C"
    {
        int32 L_var_out;

        L_var_out = L_var1 + L_var2;

        if (((L_var1 ^ L_var2) & MIN_32) == 0)  /* same sign ? */
        {
            if ((L_var_out ^ L_var1) & MIN_32)  /* addition matches sign ? */
            {
                L_var_out = (L_var1 >> 31) ^ MAX_32;
        //L_var_out = L_var1 + L_var2;
        if (L_var2 < 0) {
            if (L_var1 < MIN_32 - L_var2) {
                return MIN_32;
            }
        } else {
            if (L_var1 > MAX_32 - L_var2) {
                return MAX_32;
            }
        return (L_var_out);
        }

        return L_var1 + L_var2;
    }


@@ -248,35 +250,32 @@ extern "C"

    __inline  int32 sub_int32(int32 L_var1, int32 L_var2)
    {
        int32 L_var_out;

        L_var_out = L_var1 - L_var2;

        if (((L_var1 ^ L_var2) & MIN_32) != 0)  /* different sign ? */
        {
            if ((L_var_out ^ L_var1) & MIN_32)  /* difference matches sign ? */
            {
                L_var_out = (L_var1 >> 31) ^ MAX_32;
        //L_var_out = L_var1 - L_var2;
        if (L_var2 < 0) {
            if (L_var1 > MAX_32 + L_var2) {
                return  MAX_32;
            }
        } else {
            if (L_var1 < MIN_32 + L_var2) {
                return MIN_32;
            }
        }
        return (L_var_out);

        return L_var1 - L_var2;
    }



    /*----------------------------------------------------------------------------

         Function Name : mac_16by16_to_int32
         Function Name : mul_16by16_to_int32

         Multiply var1 by var2 and shift the result left by 1. Add the 32 bit
         result to L_var3 with saturation, return a 32 bit result:
              L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)).
         mul_16by16_to_int32 is the 32 bit result of the multiplication of var1
         times var2 with one shift left i.e.:
              L_mult(var1,var2) = L_shl((var1 times var2),1) and
              L_mult(-32768,-32768) = 2147483647.

         Inputs :

          L_var3   32 bit long signed integer (int32) whose value falls in the
                   range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.

          var1
                   16 bit short signed integer (int16) whose value falls in the
                   range : 0xffff 8000 <= var1 <= 0x0000 7fff.
@@ -285,7 +284,6 @@ extern "C"
                   16 bit short signed integer (int16) whose value falls in the
                   range : 0xffff 8000 <= var1 <= 0x0000 7fff.


         Return Value :
                   32 bit long signed integer (int32) whose value falls in the
                   range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
@@ -293,9 +291,8 @@ extern "C"
     ----------------------------------------------------------------------------*/


    __inline  int32 mac_16by16_to_int32(int32 L_var3, int16 var1, int16 var2)
    __inline  int32 mul_16by16_to_int32(int16 var1, int16 var2)
    {
        int32 L_var_out;
        int32 L_mul;

        L_mul  = ((int32) var1 * (int32) var2);
@@ -309,28 +306,17 @@ extern "C"
            L_mul = MAX_32;     /* saturation */
        }

        L_var_out = L_var3 + L_mul;

        if (((L_mul ^ L_var3) & MIN_32) == 0)  /* same sign ? */
        {
            if ((L_var_out ^ L_var3) & MIN_32)  /* addition matches sign ? */
            {
                L_var_out = (L_var3 >> 31) ^ MAX_32;
            }
        }
        return (L_mul);

        return (L_var_out);
    }



    /*----------------------------------------------------------------------------

         Function Name : msu_16by16_from_int32
         Function Name : mac_16by16_to_int32

         Multiply var1 by var2 and shift the result left by 1. Subtract the 32 bit
         Multiply var1 by var2 and shift the result left by 1. Add the 32 bit
         result to L_var3 with saturation, return a 32 bit result:
              L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)).
              L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)).

         Inputs :

@@ -352,46 +338,26 @@ extern "C"

     ----------------------------------------------------------------------------*/

    __inline  int32 msu_16by16_from_int32(int32 L_var3, int16 var1, int16 var2)
    {
        int32 L_var_out;
        int32 L_mul;

        L_mul  = ((int32) var1 * (int32) var2);

        if (L_mul != 0x40000000)
        {
            L_mul <<= 1;
        }
        else
        {
            L_mul = MAX_32;     /* saturation */
        }

        L_var_out = L_var3 - L_mul;

        if (((L_mul ^ L_var3) & MIN_32) != 0)  /* different sign ? */
        {
            if ((L_var_out ^ L_var3) & MIN_32)  /* difference matches sign ? */
    __inline  int32 mac_16by16_to_int32(int32 L_var3, int16 var1, int16 var2)
    {
                L_var_out = (L_var3 >> 31) ^ MAX_32;
            }
        }

        return (L_var_out);
        return add_int32(L_var3, mul_16by16_to_int32(var1, var2));
    }


    /*----------------------------------------------------------------------------

         Function Name : mul_16by16_to_int32
         Function Name : msu_16by16_from_int32

         mul_16by16_to_int32 is the 32 bit result of the multiplication of var1
         times var2 with one shift left i.e.:
              L_mult(var1,var2) = L_shl((var1 times var2),1) and
              L_mult(-32768,-32768) = 2147483647.
         Multiply var1 by var2 and shift the result left by 1. Subtract the 32 bit
         result to L_var3 with saturation, return a 32 bit result:
              L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)).

         Inputs :

          L_var3   32 bit long signed integer (int32) whose value falls in the
                   range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.

          var1
                   16 bit short signed integer (int16) whose value falls in the
                   range : 0xffff 8000 <= var1 <= 0x0000 7fff.
@@ -400,31 +366,18 @@ extern "C"
                   16 bit short signed integer (int16) whose value falls in the
                   range : 0xffff 8000 <= var1 <= 0x0000 7fff.


         Return Value :
                   32 bit long signed integer (int32) whose value falls in the
                   range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.

     ----------------------------------------------------------------------------*/


    __inline  int32 mul_16by16_to_int32(int16 var1, int16 var2)
    {
        int32 L_mul;

        L_mul  = ((int32) var1 * (int32) var2);

        if (L_mul != 0x40000000)
        {
            L_mul <<= 1;
        }
        else
    __inline  int32 msu_16by16_from_int32(int32 L_var3, int16 var1, int16 var2)
    {
            L_mul = MAX_32;     /* saturation */
        return sub_int32(L_var3, mul_16by16_to_int32(var1, var2));
    }

        return (L_mul);

    }

    /*----------------------------------------------------------------------------

@@ -447,7 +400,7 @@ extern "C"
     ----------------------------------------------------------------------------*/
    __inline int16 amr_wb_round(int32 L_var1)
    {
        if (L_var1 != MAX_32)
        if (L_var1 <= (MAX_32 - 0x00008000L))
        {
            L_var1 +=  0x00008000L;
        }