xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #465: image-pixels-reallocate-fix.patch

File image-pixels-reallocate-fix.patch, 3.3 KB (added by Antoine Martin, 6 years ago)

work in progress patch to fix use-after-free

  • xpra/codecs/argb/argb.pyx

     
    1414cdef extern from "string.h":
    1515    void * memcpy(void * destination, void * source, size_t num)
    1616
     17cdef extern from "stdlib.h":
     18    void free(void* mem)
    1719
     20
    1821import struct
    1922from xpra.log import Logger
    2023log = Logger("encoding")
     
    247250    assert object_as_buffer(pixels, <const void**> &img_buf, &img_buf_len)==0, "cannot convert %s to a readable buffer" % type(pixels)
    248251    if img_buf_len<=0:
    249252        return False
    250     cdef int out_size = rstride*height                 #desirable size we could have
     253    cdef int out_size = rstride*height                  #desirable size we could have
    251254    #is it worth re-striding to save space:
    252255    if img_buf_len-out_size<1024 or out_size*110/100>img_buf_len:
    253256        return False
     
    254257    #we'll save at least 1KB and 10%, do it
    255258    #Note: we could also change the pixel format whilst we're at it
    256259    # and convert BGRX to RGB for example (assuming RGB is also supported by the client)
    257     #this buffer is allocated by the imagewrapper, so it will be freed after use for us:
    258     cdef unsigned long ptr = int(image.allocate_buffer(out_size))
    259     assert ptr>0
     260    #this buffer is allocated by the imagewrapper, so it will be freed after use for us,
     261    #but we need to tell allocate_buffer not to free the current buffer (if there is one),
     262    #and we have to deal with this ourselves after we're done copying it
     263    cdef unsigned long ptr
     264
     265    #save pixels pointer to free later:
     266    ptr = int(image.get_pixel_ptr())
     267    cdef unsigned long pixptr = ptr
     268
     269    ptr = int(image.allocate_buffer(out_size, False))
     270    assert ptr>0, "allocate_buffer failed"
    260271    cdef unsigned char *out = <unsigned char*> ptr
     272
    261273    cdef int ry = height
    262     while ry>0:
     274    for 0 <= ry < height:
    263275        memcpy(out, img_buf, rstride)
    264276        out += rstride
    265277        img_buf += stride
    266         ry -= 1
     278    if pixptr:
     279        free(<void *> pixptr)
    267280    log("restride_image: %s pixels re-stride saving %i%% from %s (%s bytes) to %s (%s bytes)" % (pixel_format, 100-100*out_size/img_buf_len, stride, img_buf_len, rstride, out_size))
    268281    image.set_rowstride(rstride)
    269282    return True
  • xpra/x11/bindings/ximage.pyx

     
    328328        cdef const unsigned char * buf = NULL
    329329        cdef Py_ssize_t buf_len = 0
    330330        assert object_as_buffer(pixels, <const void**> &buf, &buf_len)==0
    331         self.allocate_buffer(buf_len)
     331        self.allocate_buffer(buf_len, 1)
    332332        memcpy(self.pixels, buf, buf_len)
    333333
    334     def allocate_buffer(self, buf_len):
    335         if self.pixels!=NULL:
     334    def get_pixel_ptr(self):
     335        return int(<unsigned long> self.pixels)
     336
     337    def allocate_buffer(self, Py_ssize_t buf_len, int free_existing=1):
     338        if self.pixels!=NULL and free_existing!=0:
    336339            free(self.pixels)
    337             self.pixels = NULL
     340        self.pixels = NULL
    338341        #Note: we can't free the XImage, because it may
    339342        #still be used somewhere else (see XShmWrapper)
    340343        if posix_memalign(<void **> &self.pixels, 64, buf_len):