| Summary: | Segmentation fault when using SDL_DisplayYUVOverlay | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Paul <kylester36> |
| Component: | video | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | ||
| Version: | 1.2.14 | ||
| Hardware: | x86 | ||
| OS: | Linux | ||
This is fixed in revision abb56f7699ea, thanks! Okay, I put in a safer fix in revision d7cdc25af9a2 |
Hi, Firstly, accept my apologies if I'm going about this the wrong way -- I'm a new user to SDL in the specific, and to Open source development in the general. I've some software I've written (for Linux) that interacts with a camera, and uses SDL to display the images on the system. My application was occasionally getting a segmentation fault when displaying images from the camera, depending on the image size, and the size of the display window. I chased down the error, and I found the 'crux' of the error seems to be from within the SDL_stretch.c module. More specifically, here is a code snippet from SDL_SoftStretch: #ifdef USE_ASM_STRETCH /* Write the opcodes for this stretch */ if ( (bpp == 3) || (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) { use_asm = SDL_FALSE; } #endif and the corresponding definition of generate_rowbytes is found as follows: static unsigned char copy_row[4096] PAGE_ALIGNED; static int generate_rowbytes(int src_w, int dst_w, int bpp) { static struct { int bpp; int src_w; int dst_w; int status; } last; int i; int pos, inc; unsigned char *eip; unsigned char load, store; /* See if we need to regenerate the copy buffer */ if ( (src_w == last.src_w) && (dst_w == last.dst_w) && (bpp == last.bpp) ) { return(last.status); } last.bpp = bpp; last.src_w = src_w; last.dst_w = dst_w; last.status = -1; switch (bpp) { case 1: load = LOAD_BYTE; store = STORE_BYTE; break; case 2: case 4: load = LOAD_WORD; store = STORE_WORD; break; default: SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp); return(-1); } #ifdef HAVE_MPROTECT /* Make the code writeable */ if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_WRITE) < 0 ) { SDL_SetError("Couldn't make copy buffer writeable"); return(-1); } #endif pos = 0x10000; inc = (src_w << 16) / dst_w; eip = copy_row; for ( i=0; i<dst_w; ++i ) { while ( pos >= 0x10000L ) { if ( bpp == 2 ) { *eip++ = PREFIX16; } *eip++ = load; pos -= 0x10000L; } if ( bpp == 2 ) { *eip++ = PREFIX16; } *eip++ = store; pos += inc; } *eip++ = RETURN; /* Verify that we didn't overflow (too late!!!) */ if ( eip > (copy_row+sizeof(copy_row)) ) { SDL_SetError("Copy buffer overflow"); return(-1); } #ifdef HAVE_MPROTECT /* Make the code executable but not writeable */ if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_EXEC) < 0 ) { SDL_SetError("Couldn't make copy buffer executable"); return(-1); } #endif last.status = 0; return(0); } The problem I'm having is with the copy_row structure (which BTW -- is really cool, once I figured out what it wsa doing). In my case the images coming from the camera are 'large' (1600x1200), and the 'scaling' factor is kind of big too -- I'm attempting to display the image in a 640x640 window. The problem I'm encountering is, the copy_row structure is being overflown, corrupting what happens to reside below the copy_buffer structure. This (eventually) causes a segmentation fault. There is code above that 'detects' the overflow, and returns -1 of that is the case -- but as you can see from its use in SDL_SoftStretch, it just makes a point of not using the assembly routines, and carries on none the wiser that damage had been done. At a suggestion, I changed my local copy to add another static structure after copy_row (called copy_row_limit). I then changed the loop shown above too: for ( i=0; i<dst_w && eip<copy_row_limit; ++i ) { while ( pos >= 0x10000L ) { if ( bpp == 2 ) { *eip++ = PREFIX16; } *eip++ = load; pos -= 0x10000L; } if ( bpp == 2 ) { *eip++ = PREFIX16; } *eip++ = store; pos += inc; } *eip++ = RETURN; /* Verify that we didn't overflow (too late!!!) */ if ( eip > copy_row_limit ) { SDL_SetError("Copy buffer overflow"); return(-1); } I sized the copy_row_limit to 8 + (4 times the maximum scaling factor that I permit (8)). Thanks. /Paul