Document how to call setjmp() correctly.
The jmp_buf after a setjmp() call is valid only for the duration of the
function that calls setjmp(). This is documented in:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/longjmp.html
https://en.cppreference.com/w/c/program/longjmp
Therefore the function that calls setjmp() must reset the 'setjmp'
boolean field to 0 (to indicate that the jmp_buf is invalid) before it
returns.
The call_setjmp() function removed in commit
f3ac65169d3ab435725aff888045617bc6c8ca8e did not meet this requirement
because it set the 'setjmp' field to 1 before one return statement,
therefore it was incorrect.
BUG=oss-fuzz:9463
Change-Id: I2f8a7e73910d298a961ebd3c9c1c371fa0ffe121
diff --git a/aom/internal/aom_codec_internal.h b/aom/internal/aom_codec_internal.h
index 84ea4ee..88bf78e 100644
--- a/aom/internal/aom_codec_internal.h
+++ b/aom/internal/aom_codec_internal.h
@@ -417,7 +417,7 @@
aom_codec_err_t error_code;
int has_detail;
char detail[80];
- int setjmp;
+ int setjmp; // Boolean: whether 'jmp' is valid.
jmp_buf jmp;
};
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 990357d..3bc4804 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -1229,6 +1229,9 @@
volatile aom_enc_frame_flags_t flags = enc_flags;
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
if (setjmp(cpi->common.error.jmp)) {
cpi->common.error.setjmp = 0;
res = update_error_state(ctx, &cpi->common.error);
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 18ca9d5..6dbc4f3 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -3071,6 +3071,9 @@
ThreadData *const td = thread_data->td;
uint8_t allow_update_cdf;
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
if (setjmp(thread_data->error_info.jmp)) {
thread_data->error_info.setjmp = 0;
thread_data->td->xd.corrupted = 1;
@@ -3222,6 +3225,9 @@
AV1DecRowMTInfo *frame_row_mt_info = &pbi->frame_row_mt_info;
td->xd.corrupted = 0;
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
if (setjmp(thread_data->error_info.jmp)) {
thread_data->error_info.setjmp = 0;
thread_data->td->xd.corrupted = 1;
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c
index 318d628..e978fad 100644
--- a/av1/decoder/decoder.c
+++ b/av1/decoder/decoder.c
@@ -82,6 +82,9 @@
av1_zero(*pbi);
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
if (setjmp(cm->error.jmp)) {
cm->error.setjmp = 0;
av1_decoder_remove(pbi);
@@ -448,6 +451,9 @@
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
if (setjmp(cm->error.jmp)) {
const AVxWorkerInterface *const winterface = aom_get_worker_interface();
int i;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 25b84fc..13ea32e 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -2435,6 +2435,9 @@
av1_zero(*cpi);
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
if (setjmp(cm->error.jmp)) {
cm->error.setjmp = 0;
av1_remove_compressor(cpi);