details: https://hg.nginx.org/njs/rev/b7c4e0f714a9 branches: changeset: 1902:b7c4e0f714a9 user: Dmitry Volyntsev <xei...@nginx.com> date: Tue Jun 28 23:04:00 2022 -0700 description: Fixed break instruction in a try-catch block.
Previously, JUMP offset for a break instruction inside a try-catch block was not set to a correct offset during code generation when a return instruction was present in inner try-catch block. The fix is to update the JUMP offset appropriately. This closes #553 issue on Github. diffstat: src/njs_generator.c | 41 +++++++++++++++++++++++++++++++++- src/test/njs_unit_test.c | 56 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 83 insertions(+), 14 deletions(-) diffs (140 lines): diff -r 116b09a57817 -r b7c4e0f714a9 src/njs_generator.c --- a/src/njs_generator.c Tue Jun 28 22:36:38 2022 -0700 +++ b/src/njs_generator.c Tue Jun 28 23:04:00 2022 -0700 @@ -4495,6 +4495,11 @@ njs_generate_try_catch(njs_vm_t *vm, njs NJS_GENERATOR_ALL, &ctx->try_exit_label); + /* + * block can be NULL when &ctx->try_exit_label is "@return" + * for outermost try-catch block. + */ + if (block != NULL) { patch = njs_generate_make_exit_patch(vm, block, &ctx->try_exit_label, @@ -4503,6 +4508,26 @@ njs_generate_try_catch(njs_vm_t *vm, njs if (njs_slow_path(patch == NULL)) { return NJS_ERROR; } + + } else { + + /* + * when block == NULL, we still want to patch the "finally" + * instruction break_offset. + */ + + block = njs_generate_find_block(vm, generator->block, + NJS_GENERATOR_ALL, + &no_label); + + if (block != NULL) { + patch = njs_generate_make_exit_patch(vm, block, &no_label, + njs_code_offset(generator, finally) + + offsetof(njs_vmcode_finally_t, break_offset)); + if (njs_slow_path(patch == NULL)) { + return NJS_ERROR; + } + } } } } @@ -4669,8 +4694,7 @@ njs_generate_try_end(njs_vm_t *vm, njs_g * outermost try-catch block. */ block = njs_generate_find_block(vm, generator->block, - NJS_GENERATOR_ALL - | NJS_GENERATOR_TRY, dest_label); + NJS_GENERATOR_ALL, dest_label); if (block != NULL) { patch = njs_generate_make_exit_patch(vm, block, dest_label, njs_code_offset(generator, finally) @@ -4678,6 +4702,19 @@ njs_generate_try_end(njs_vm_t *vm, njs_g if (njs_slow_path(patch == NULL)) { return NJS_ERROR; } + + } else { + + block = njs_generate_find_block(vm, generator->block, + NJS_GENERATOR_ALL, &no_label); + if (block != NULL) { + patch = njs_generate_make_exit_patch(vm, block, &no_label, + njs_code_offset(generator, finally) + + offsetof(njs_vmcode_finally_t, break_offset)); + if (njs_slow_path(patch == NULL)) { + return NJS_ERROR; + } + } } } diff -r 116b09a57817 -r b7c4e0f714a9 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Jun 28 22:36:38 2022 -0700 +++ b/src/test/njs_unit_test.c Tue Jun 28 23:04:00 2022 -0700 @@ -3411,20 +3411,52 @@ static njs_unit_test_t njs_test[] = njs_str("a,2") }, { njs_str("function f(n) { " - " var r1 = 0, r2 = 0, r3 = 0;" - " a:{ try { try { " - " if (n == 0) { break a; } " - " if (n == 1) { throw 'a'; } " - " } " - " catch (e) { break a; } finally { r1++; } } " - " catch (e) {} " - " finally { r2++; } " - " r3++; " - " }; " - "return [r1, r2, r3]" - "}; njs.dump([f(0), f(1), f(3)])"), + " var r1 = 0, r2 = 0, r3 = 0;" + " a:{ try { try { " + " if (n == 0) { break a; } " + " if (n == 1) { throw 'a'; } " + " } " + " catch (e) { break a; } finally { r1++; } } " + " catch (e) {} " + " finally { r2++; } " + " r3++; " + " }; " + "return [r1, r2, r3]" + "}; njs.dump([f(0), f(1), f(3)])"), njs_str("[[1,1,0],[1,1,0],[1,1,1]]") }, + + { njs_str("function f(n) {" + " while (1)" + " try {" + " if (n == 0) { break; }" + " if (n == 1) { throw 'a'; }" + "" + " try { return 42; }" + " catch (a) {}" + "" + " } catch (b) { return b; }" + "};" + "njs.dump([f(0), f(1), f(2)])"), + njs_str("[undefined,'a',42]") }, + + { njs_str("function f(n, r) {" + " while (1)" + " try {" + " if (n == 0) { break; }" + " if (n == 1) { throw 'a'; }" + "" + " try { return 42; }" + " catch (a) {}" + " finally { r.push('in');}" + "" + " } catch (b) { return b; }" + " finally { r.push('out'); }" + "};" + "function g(n) { var r = []; return [f(n, r), r]}" + "njs.dump([g(0), g(1), g(2)])"), + njs_str("[[undefined,['out']],['a',['out']],[42,['in','out']]]") }, + /**/ { njs_str("function f() { Object.prototype.toString = 1; };" _______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org