[Python-Dev] [Python-checkins] cpython (merge 3.2 -> default): Fix out of bounds read in long_new() for empty bytes with an explicit base.

Stefan Krah stefan at bytereef.org
Wed Sep 12 16:22:59 CEST 2012


christian.heimes <python-checkins at python.org> wrote:
>   Fix out of bounds read in long_new() for empty bytes with an explicit base. int(b'', somebase) calls PyLong_FromString() with char* of length 1 but the function accesses the first argument at offset 1. CID 715359
> 
> files:
>   Objects/longobject.c |  4 ++--
>   1 files changed, 2 insertions(+), 2 deletions(-)
> 
> 
> diff --git a/Objects/longobject.c b/Objects/longobject.c
> --- a/Objects/longobject.c
> +++ b/Objects/longobject.c
> @@ -4285,8 +4285,8 @@
>              string = PyByteArray_AS_STRING(x);
>          else
>              string = PyBytes_AS_STRING(x);
> -        if (strlen(string) != (size_t)size) {
> -            /* We only see this if there's a null byte in x,
> +        if (strlen(string) != (size_t)size || !size) {
> +            /* We only see this if there's a null byte in x or x is empty,
>                 x is a bytes or buffer, *and* a base is given. */
>              PyErr_Format(PyExc_ValueError,
>                           "invalid literal for int() with base %d: %R",


This is a false positive:                                                                                    
                                                                                                             
    Assumption: string == ""                                                                                 
                                                                                                             
    Call:  PyLong_FromString("", NULL, (int)base);                                                           
                                                                                                             
        Now: str == ""                                                                                       
                                                                                                             
        Coverity claims an invalid access at str[1]:                                                         
                                                                                                             
            if (str[0] == '0' &&                                                                             
                ((base == 16 && (str[1] == 'x' || str[1] == 'X')) ||                                         
                (base == 8  && (str[1] == 'o' || str[1] == 'O')) ||                                          
                (base == 2  && (str[1] == 'b' || str[1] == 'B'))))                                           
                                                                                                             
        But str[1] is never accessed due to shortcut evaluation.                                             
                                                                                                             
                                                                                                             
Coverity appears to have serious problems with shortcut evaluations in many                                  
places.                                                                                                      
                                                                                                             
                                                                                                             
Stefan Krah                                                                                                  
                                     




More information about the Python-Dev mailing list