ImBuf: pass the number of bytes read to 'is_a' callbacks

Previously the header was a fixed size and assumed to be zeroed.
Now read in bytes up to `HEADER_SIZE`, pass the number or bytes
read to the callback which must not read past those bytes.
This commit is contained in:
Campbell Barton 2020-11-12 12:19:12 +11:00
parent fa81a42539
commit f284a40385
1 changed files with 22 additions and 36 deletions

View File

@ -120,8 +120,8 @@ const char *imb_ext_audio[] = {
/* Increased from 32 to 64 because of the bitmaps header size. */
#define HEADER_SIZE 64
static bool imb_ispic_read_header_from_filepath(const char *filepath,
unsigned char buf[HEADER_SIZE])
static ssize_t imb_ispic_read_header_from_filepath(const char *filepath,
unsigned char buf[HEADER_SIZE])
{
BLI_stat_t st;
int fp;
@ -133,43 +133,27 @@ static bool imb_ispic_read_header_from_filepath(const char *filepath,
}
if (BLI_stat(filepath, &st) == -1) {
return false;
return -1;
}
if (((st.st_mode) & S_IFMT) != S_IFREG) {
return false;
return -1;
}
if ((fp = BLI_open(filepath, O_BINARY | O_RDONLY, 0)) == -1) {
return false;
return -1;
}
memset(buf, 0, HEADER_SIZE);
if (read(fp, buf, HEADER_SIZE) <= 0) {
close(fp);
return false;
}
const ssize_t size = read(fp, buf, HEADER_SIZE);
close(fp);
return true;
return size;
}
int IMB_ispic_type_from_memory(const unsigned char *mem, const size_t mem_size)
int IMB_ispic_type_from_memory(const unsigned char *buf, const size_t buf_size)
{
unsigned char buf_static[HEADER_SIZE];
const unsigned char *buf;
if (mem_size >= HEADER_SIZE) {
buf = buf_static;
}
else {
memset(buf_static, 0, HEADER_SIZE);
memcpy(buf_static, mem, mem_size);
buf = buf_static;
}
for (const ImFileType *type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->is_a != NULL) {
if (type->is_a(buf, HEADER_SIZE)) {
if (type->is_a(buf, buf_size)) {
return type->filetype;
}
}
@ -181,17 +165,19 @@ int IMB_ispic_type_from_memory(const unsigned char *mem, const size_t mem_size)
int IMB_ispic_type(const char *filepath)
{
unsigned char buf[HEADER_SIZE];
if (!imb_ispic_read_header_from_filepath(filepath, buf)) {
const ssize_t buf_size = imb_ispic_read_header_from_filepath(filepath, buf);
if (buf_size <= 0) {
return 0;
}
return IMB_ispic_type_from_memory(buf, HEADER_SIZE);
return IMB_ispic_type_from_memory(buf, (size_t)buf_size);
}
bool IMB_ispic_type_matches(const char *filepath, int filetype)
{
unsigned char buf[HEADER_SIZE];
if (!imb_ispic_read_header_from_filepath(filepath, buf)) {
return 0;
const ssize_t buf_size = imb_ispic_read_header_from_filepath(filepath, buf);
if (buf_size <= 0) {
return false;
}
for (const ImFileType *type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
@ -200,11 +186,11 @@ bool IMB_ispic_type_matches(const char *filepath, int filetype)
* Keep the check for developers. */
BLI_assert(type->is_a != NULL);
if (type->is_a != NULL) {
return type->is_a(buf, HEADER_SIZE);
return type->is_a(buf, (size_t)buf_size);
}
}
}
return 0;
return false;
}
#undef HEADER_SIZE
@ -360,7 +346,6 @@ static int isffmpeg(const char *filepath)
int imb_get_anim_type(const char *filepath)
{
int type;
BLI_stat_t st;
BLI_assert(!BLI_path_is_rel(filepath));
@ -390,7 +375,7 @@ int imb_get_anim_type(const char *filepath)
if (ismovie(filepath)) {
return ANIM_MOVIE;
}
#else
#else /* !_WIN32 */
if (BLI_stat(filepath, &st) == -1) {
return 0;
}
@ -410,9 +395,10 @@ int imb_get_anim_type(const char *filepath)
if (isavi(filepath)) {
return ANIM_AVI;
}
#endif
type = IMB_ispic(filepath);
if (type) {
#endif /* !_WIN32 */
/* Assume a single image is part of an image sequence. */
if (IMB_ispic(filepath)) {
return ANIM_SEQUENCE;
}