LUbuntu 19.10 : double free detected in tcache 2

Hi,

I’m using SDL-2.0.10 under LUbuntu 19.10, Windows/MINGW, FreeBSD 12.1 and OpenBSD 6.6

The following code is causing a crash under linux and openbsd if I uncomment the penultimate line.

There might be something wrong in either SDL_Free_xxx.

Time to fill a bug report?

KR,
-pj

void x_bitmap_ctor(x_bitmap * bitmap, const uint8_t * bmp_data, int bmp_size)
{
    x_surface_ctor(&(bitmap->surface));

    SDL_Surface * bmp = NULL;

    SDL_RWops * rw = SDL_RWFromConstMem((const void *) bmp_data, bmp_size);
    if(!rw) {
        M_APP_LOG_ERROR("load_bmp: SDL_RWFromConstMem: %s", SDL_GetError());
        return;
    }

    /* we suppose of a 8-bit BMP, no convert yet (to be studied) */
    bmp = SDL_LoadBMP_RW(rw, 1);
    if(!bmp) {
        M_APP_LOG_ERROR("load_bmp: SDL_LoadBMP_RW: %s", SDL_GetError());
        SDL_FreeRW(rw);
        return;
    }

    M_APP_LOG_DEBUG("BMP Loaded: w=%d h=%d pitch=%d indexed=%d bits/p=%d bytes/p=%d",
        bmp->w, bmp->h, bmp->pitch,
        SDL_ISPIXELFORMAT_INDEXED(bmp->format->format),
        bmp->format->BitsPerPixel, bmp->format->BytesPerPixel);

    if( !SDL_ISPIXELFORMAT_INDEXED(bmp->format->format) || bmp->format->BitsPerPixel != 8 ) {
        M_APP_LOG_ERROR("load_bmp: invalid pixel format");
        SDL_FreeRW(rw);
        SDL_FreeSurface(bmp);
        return;
    }
    
    x_surface_resize(&(bitmap->surface), bmp->w, bmp->h);
    memcpy(bitmap->surface.pixels, bmp->pixels, bmp->w *bmp->h);

    /* copy BMP palette to the x_palette */
    SDL_Palette * sdl_palette = bmp->format->palette;
    assert(sdl_palette);
    for(int i = 0; i < sdl_palette->ncolors; i++) {
        x_palette_set_color_3i(&(bitmap->palette), i, sdl_palette->colors[i].r, sdl_palette->colors[i].g, sdl_palette->colors[i].b);
    }

    // TODO: temporary to avoid error under LUnbuntu 19.10 and OpenBSD 6.6
    // double free detected in tcache 2 (other error under openbsd)
    // SDL_FreeRW(rw);
    SDL_FreeSurface(bmp);
}

Rather time to read the documentation a bit:

https://wiki.libsdl.org/SDL_LoadBMP_RW

You call it with 1 as argument for freesrc which means this function closes that SDL_RWops on its own. No need to free it later on.

You’re right I should have better RTFM… and the other platforms are too permissive :wink:

Do you know the behavior in case of error ?

EDIT: reading the source of video/SDL_bmp.c SDL_RWclose() is called even in case of error.