Possible Signed Overflow for Luma Chunks
Hello,
I've spent a bit of time implementing my own version of the QOI encode/decoder
using Rust. The intent was that the output would binary compatible with that of
the reference decoder. During testing however, I did notice a small discrepancy
between in (at least) one of the testfiles (qoi_test_images/testcard.qoi).
After some debugging, I noticed that I handled the Diff/Luma chunks incorrectly. After fixing that though, Rust noticed that the expression to compute the Luma differences can actually overflow:
signed char vr = px.rgba.r - px_prev.rgba.r;
signed char vg = px.rgba.g - px_prev.rgba.g;
signed char vb = px.rgba.b - px_prev.rgba.b;
printf("Pixel=%d\n", px_pos / 4);
printf("dr=%d, dg=%d, db=%d\n", vr, vg, vb);
signed char vg_r = vr - vg;
signed char vg_b = vb - vg;For the testfile above, this yields the output:
Pixel=6168
dr=72, dg=-105, db=-127Which really should overflow the vr - vg expression. Then again, maybe I'm
missing some obscure integer promotion rule? I even tried adding sanitizers to
the QOI build files when generating this:
CC ?= clang
CFLAGS_BENCH ?= -std=gnu99 -g3 -fsanitize=signed-integer-overflow $(shell pkg-config --cflags stb)
LFLAGS_BENCH ?= -lpng
CFLAGS_CONV ?= -std=c99 -g3 -fsanitize=signed-integer-overflow $(shell pkg-config --cflags stb)But they didn't trigger on this, which makes me unsure whether it is "really" a bug. Either way, given that signed overflow is typically regarded as undefined behavior according to the C/C++ standards, I think that this should be changed, or at least documented with a mild warning above the statements.
Source: phoboslab/qoi