cleanup: secure reading some stream names

This commit is contained in:
bnnm 2024-09-08 21:05:53 +02:00
parent 4e9d4905d9
commit 25d2ecb59b
5 changed files with 41 additions and 39 deletions

View File

@ -243,7 +243,7 @@ VGMSTREAM* init_vgmstream_nus3bank(STREAMFILE* sf) {
vgmstream->num_streams = total_subsongs;
if (name_offset)
read_string(vgmstream->stream_name, name_size, name_offset, sf);
read_string_sz(vgmstream->stream_name, STREAM_NAME_SIZE, name_size, name_offset, sf);
close_streamfile(temp_sf);

View File

@ -197,7 +197,7 @@ VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) {
/* actual Ogg init */
ogg_vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
if (ogg_vgmstream && name_offset)
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, sf);
read_string(ogg_vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf);
return ogg_vgmstream;
}
#endif

View File

@ -339,58 +339,45 @@ static void sead_cat(char* dst, int dst_max, const char* src) {
}
static void build_readable_sab_name(sead_header_t* sead, STREAMFILE* sf, uint32_t sndname_offset, uint32_t sndname_size) {
char * buf = sead->readable_name;
char* buf = sead->readable_name;
int buf_size = sizeof(sead->readable_name);
char descriptor[255], name[255];
if (sead->filename_size > 255 || sndname_size > 255)
goto fail;
char descriptor[256], name[256];
if (buf[0] == '\0') { /* init */
read_string(descriptor,sead->filename_size+1, sead->filename_offset, sf);
read_string(name, sndname_size+1, sndname_offset, sf);
read_string_sz(descriptor, sizeof(descriptor), sead->filename_size, sead->filename_offset, sf);
read_string_sz(name, sizeof(name), sndname_size, sndname_offset, sf);
snprintf(buf,buf_size, "%s/%s", descriptor, name);
}
else { /* add */
read_string(name, sndname_size+1, sndname_offset, sf);
read_string_sz(name, sizeof(name), sndname_size, sndname_offset, sf);
sead_cat(buf, buf_size, "; ");
sead_cat(buf, buf_size, name);
}
return;
fail:
VGM_LOG("SEAD: bad sab name found\n");
}
static void build_readable_mab_name(sead_header_t* sead, STREAMFILE* sf) {
char * buf = sead->readable_name;
char* buf = sead->readable_name;
int buf_size = sizeof(sead->readable_name);
char descriptor[255], name[255], mode[255];
char descriptor[256], name[256], mode[256];
if (sead->filename_size > 255 || sead->muscname_size > 255 || sead->sectname_size > 255 || sead->modename_size > 255)
goto fail;
read_string(descriptor,sead->filename_size+1,sead->filename_offset, sf);
//read_string(filename,sead->muscname_size+1,sead->muscname_offset, sf); /* same as filename, not too interesting */
read_string_sz(descriptor, sizeof(descriptor), sead->filename_size, sead->filename_offset, sf);
//read_string_sz(filename, sizeof(filename), sead->muscname_size, sead->muscname_offset, sf); /* same as filename, not too interesting */
if (sead->sectname_offset)
read_string(name,sead->sectname_size+1,sead->sectname_offset, sf);
read_string_sz(name, sizeof(name), sead->sectname_size,sead->sectname_offset, sf);
else if (sead->instname_offset)
read_string(name,sead->instname_size+1,sead->instname_offset, sf);
read_string_sz(name, sizeof(name), sead->instname_size, sead->instname_offset, sf);
else
strcpy(name, "?");
if (sead->modename_offset > 0)
read_string(mode,sead->modename_size+1,sead->modename_offset, sf);
read_string_sz(mode, sizeof(mode), sead->modename_size,sead->modename_offset, sf);
/* default mode in most files */
if (sead->modename_offset == 0 || strcmp(mode, "Mode") == 0 || strcmp(mode, "Mode0") == 0)
snprintf(buf,buf_size, "%s/%s", descriptor, name);
else
snprintf(buf,buf_size, "%s/%s/%s", descriptor, name, mode);
return;
fail:
VGM_LOG("SEAD: bad mab name found\n");
}
static void parse_sead_mab_name(sead_header_t* sead, STREAMFILE* sf) {

View File

@ -120,29 +120,41 @@ size_t read_bom(STREAMFILE* sf) {
return 0x00;
}
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
size_t pos;
size_t read_string_sz(char* buf, size_t buf_size, size_t string_size, off_t offset, STREAMFILE* sf) {
for (pos = 0; pos < buf_size; pos++) {
// read up to buf, or stop before if size is set; in either case will stop at 0x00
size_t max_size = buf_size;
if (string_size > 0 && string_size < max_size)
max_size = string_size + 1;
for (size_t pos = 0; pos < max_size; pos++) {
uint8_t byte = read_u8(offset + pos, sf);
char c = (char)byte;
if (buf) buf[pos] = c;
if (c == '\0')
if (buf) buf[pos] = (char)byte;
// done
if (byte == '\0')
return pos;
if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */
// null at maxsize and don't validate (expected to be garbage)
if (pos + 1 == max_size) {
if (buf) buf[pos] = '\0';
return buf_size;
return max_size;
}
/* UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use */
// UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use
if (byte < 0x20 || byte > 0xF0)
goto fail;
break;
}
fail:
// error or wrong max_size
if (buf) buf[0] = '\0';
return 0;
}
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
return read_string_sz(buf, buf_size, 0, offset, sf);
}
size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian) {
size_t pos, offpos;
read_u16_t read_u16 = big_endian ? read_u16be : read_u16le;

View File

@ -11,7 +11,10 @@ size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_l
/* skip BOM if needed */
size_t read_bom(STREAMFILE* sf);
/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */
/* Reads a C-string (ANSI only), up to buf_size, string_size (no need to include null char), or NULL (whichever is happens first).
* Returning size and buf is optional (works as get_string_size without it). Will always null-terminate the string. */
size_t read_string_sz(char* buf, size_t buf_size, size_t string_size, off_t offset, STREAMFILE* sf);
/* same but without known string_size */
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */
size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian);