I've been on it for a long while:
This is some schrodinger bug, I can't accurately track when it occurs and when not, I tried -g, -O1, -O2 but in the end results were inconsistent, sometimes it happens, sometimes not(because it involves ub by accessing undefined ptr, see below)
Directory open for reading as a file seems to always(both FILE and ifstream) return that it read 0 bytes and has size of 2^31-1.
-sf::Shader.loadFromFile attempts to allocate 2^31-1 which throws std::bad_alloc(I have 2 gbs of ram) you probably should catch that exception up in loadFromFile and print what() to sf::err() and return false from load.
-sf::Image stbi attepts to decrement by one a pointer that has values null, 0x1, sometimes valid adresses, in the program adress space, it's just uninit ptr
typedef struct{ uint32 img_x
, img_y
; int img_n
, img_out_n
; stbi_io_callbacks io
; void *io_user_data
; int read_from_callbacks
; int buflen
; uint8 buffer_start
[128]; uint8 *img_buffer
, *img_buffer_end
;//these 2 ptrs are important uint8 *img_buffer_original
;} stbi
;unsigned char *stbi_load_from_file
(FILE
*f
, int *x
, int *y
, int *comp
, int req_comp
){ stbi s
; start_file
(&s
,f
); return stbi_load_main
(&s
,x
,y
,comp
,req_comp
);}static void start_file
(stbi
*s
, FILE
*f
){ start_callbacks
(s
, &stbi_stdio_callbacks
, (void *) f
);}static void start_callbacks
(stbi
*s
, stbi_io_callbacks
*c
, void *user
){ s
->io
= *c
; s
->io_user_data
= user
; s
->buflen
= sizeof(s
->buffer_start
); s
->read_from_callbacks
= 1; s
->img_buffer_original
= s
->buffer_start
; refill_buffer
(s
);// goes into there with these 2 pointers with undefined values in them}//the callback in refill buffer is that one, it always returns 0 for directories open as FILEstatic int stdio_read
(void *user
, char *data
, int size
){ return (int) fread(data
,1,size
,(FILE
*) user
);}static void refill_buffer
(stbi
*s
){ int n
= (s
->io.
read)(s
->io_user_data
,(char*)s
->buffer_start
,s
->buflen
); if (n
== 0) {//we go here // at end of file, treat same as if from memory s
->read_from_callbacks
= 0; s
->img_buffer
= s
->img_buffer_end
-1;//this wasnt ever initialized, sometimes its null, sometimes its 0x1, idk why *s
->img_buffer
= 0;//this line might do the segfault, writing to 0xffffffff or 0x0, in general writing into random space } else { s
->img_buffer
= s
->buffer_start
; s
->img_buffer_end
= s
->buffer_start
+ n
; }} now if we hit into own memory, we are kind of ok and go to this function,
tatic unsigned char *stbi_load_main(stbi *s, int *x, int *y, int *comp, int req_comp)
{
if (stbi_jpeg_test(s)) return stbi_jpeg_load(s,x,y,comp,req_comp);
if (stbi_png_test(s)) return stbi_png_load(s,x,y,comp,req_comp);
if (stbi_bmp_test(s)) return stbi_bmp_load(s,x,y,comp,req_comp);
if (stbi_gif_test(s)) return stbi_gif_load(s,x,y,comp,req_comp);
if (stbi_psd_test(s)) return stbi_psd_load(s,x,y,comp,req_comp);
if (stbi_pic_test(s)) return stbi_pic_load(s,x,y,comp,req_comp);
#ifndef STBI_NO_HDR
if (stbi_hdr_test(s)) {
float *hdr = stbi_hdr_load(s, x,y,comp,req_comp);
return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
}
#endif
// test tga last because it's a crappy test!
if (stbi_tga_test(s))
return stbi_tga_load(s,x,y,comp,req_comp);
return epuc("unknown image type", "Image not of any known type, or corrupt");
}
-jpeg gets 'marker' m which if not 0xd8 will return error:
#define SOI(x) ((x) == 0xd8)
if (!SOI(m)) return e("no SOI","Corrupt JPEG");
-png, bmp and gif check for the three letters of their respective format in first bytes
-psd checks for "8BPS"
-pic checks for "\x53\x80\xF6\x34"
-hdr checks for "#?RADIANCE\n" but I'm not sure if SFML doesn't define it out, but it doesn't matter
-tga discards one byte, then returns if second byte is >1 or third is unequal to any of 1 2 3 9 10 11
Since we have 0 as first and only byte, and in case of tga we run out and call refill which 'refills' with 0 again so we are basically endless stream of 0s and fail all tests. I'd say that's a bug in stbi.
-sf::SoundBuffer and sf::Music, "Failed to open sound file "." (File contains data in an unknown format.)", I don't have source of sndfile but it seems it's immune to the fact that data can't be read from seemingly ok long file
-sf::Font "Failed to load font "." (failed to create the font face)" I guess freetype is immune too..
In any case this needs more testing but shader can be fixed right away,
stbi too:
static void start_callbacks(stbi *s, stbi_io_callbacks *c, void *user)
{
s->io = *c;
s->io_user_data = user;
s->buflen = sizeof(s->buffer_start);
s->read_from_callbacks = 1;
s->img_buffer_original = s->buffer_start;
s->img_buffer_end=s->buffer_start+1;//this line fixes it because now we use the first byte from out buffer_start[128]
refill_buffer(s);
}
I think..
But I might have made mistakes, and these really need more work:
-check freetype reactions and safety
-check sndfile reactions and safety
-check behavior of directory in FILE * on various *nixes(linux definitely affected at least my lovely Fedora and netrick's lubuntu, maybe other distros and macs too?)
-just use stat or dirent or something to avoid opening directory like that?