Fix #22: avoid UB when reading ints from the stream;
This commit is contained in:
parent
30f8a39ec8
commit
dd0b04b319
45
qoi.h
45
qoi.h
@ -241,16 +241,33 @@ void *qoi_decode(const void *data, int size, int *out_w, int *out_h, int channel
|
|||||||
#define QOI_HEADER_SIZE 12
|
#define QOI_HEADER_SIZE 12
|
||||||
#define QOI_PADDING 4
|
#define QOI_PADDING 4
|
||||||
|
|
||||||
#define QOI_READ_16(B, P) ((B[P++] & 0xff) << 8 | (B[P++] & 0xff))
|
|
||||||
#define QOI_READ_32(B, P) (QOI_READ_16(B, P) << 16 | QOI_READ_16(B, P))
|
|
||||||
#define QOI_WRITE_16(B, P, V) (B[P++] = (0xff00 & V) >> 8, B[P++] = (0xff & V))
|
|
||||||
#define QOI_WRITE_32(B, P, V) (QOI_WRITE_16(B, P, V >> 16), QOI_WRITE_16(B, P, V))
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
struct { unsigned char r, g, b, a; } rgba;
|
struct { unsigned char r, g, b, a; } rgba;
|
||||||
unsigned int v;
|
unsigned int v;
|
||||||
} qoi_rgba_t;
|
} qoi_rgba_t;
|
||||||
|
|
||||||
|
void qoi_write_16(unsigned char *bytes, int *p, unsigned short v) {
|
||||||
|
bytes[(*p)++] = (0xff00 & v) >> 8;
|
||||||
|
bytes[(*p)++] = (0xff & v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) {
|
||||||
|
qoi_write_16(bytes, p, (v & 0xffff0000) >> 16);
|
||||||
|
qoi_write_16(bytes, p, (v & 0xffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int qoi_read_16(const unsigned char *bytes, int *p) {
|
||||||
|
unsigned int a = bytes[(*p)++];
|
||||||
|
unsigned int b = bytes[(*p)++];
|
||||||
|
return (a << 8) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int qoi_read_32(const unsigned char *bytes, int *p) {
|
||||||
|
unsigned int a = qoi_read_16(bytes, p);
|
||||||
|
unsigned int b = qoi_read_16(bytes, p);
|
||||||
|
return (a << 16) | b;
|
||||||
|
}
|
||||||
|
|
||||||
void *qoi_encode(const void *data, int w, int h, int channels, int *out_len) {
|
void *qoi_encode(const void *data, int w, int h, int channels, int *out_len) {
|
||||||
if (
|
if (
|
||||||
data == NULL || out_len == NULL ||
|
data == NULL || out_len == NULL ||
|
||||||
@ -268,10 +285,10 @@ void *qoi_encode(const void *data, int w, int h, int channels, int *out_len) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
QOI_WRITE_32(bytes, p, QOI_MAGIC);
|
qoi_write_32(bytes, &p, QOI_MAGIC);
|
||||||
QOI_WRITE_16(bytes, p, w);
|
qoi_write_16(bytes, &p, w);
|
||||||
QOI_WRITE_16(bytes, p, h);
|
qoi_write_16(bytes, &p, h);
|
||||||
QOI_WRITE_32(bytes, p, 0); // size, will be set later
|
qoi_write_32(bytes, &p, 0); // size, will be set later
|
||||||
|
|
||||||
const unsigned char *pixels = (const unsigned char *)data;
|
const unsigned char *pixels = (const unsigned char *)data;
|
||||||
|
|
||||||
@ -367,7 +384,7 @@ void *qoi_encode(const void *data, int w, int h, int channels, int *out_len) {
|
|||||||
*out_len = p;
|
*out_len = p;
|
||||||
|
|
||||||
p = 8;
|
p = 8;
|
||||||
QOI_WRITE_32(bytes, p, data_len);
|
qoi_write_32(bytes, &p, data_len);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,10 +396,10 @@ void *qoi_decode(const void *data, int size, int *out_w, int *out_h, int channel
|
|||||||
const unsigned char *bytes = (const unsigned char *)data;
|
const unsigned char *bytes = (const unsigned char *)data;
|
||||||
int p = 0;
|
int p = 0;
|
||||||
|
|
||||||
int magic = QOI_READ_32(bytes, p);
|
int magic = qoi_read_32(bytes, &p);
|
||||||
int w = QOI_READ_16(bytes, p);
|
int w = qoi_read_16(bytes, &p);
|
||||||
int h = QOI_READ_16(bytes, p);
|
int h = qoi_read_16(bytes, &p);
|
||||||
int data_len = QOI_READ_32(bytes, p);
|
int data_len = qoi_read_32(bytes, &p);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
w == 0 || h == 0 || magic != QOI_MAGIC ||
|
w == 0 || h == 0 || magic != QOI_MAGIC ||
|
||||||
|
Loading…
Reference in New Issue
Block a user