Improve pg_re_throw: check if sigjmp_buf is valid and report error

Xiaoran Wang <fanfuxiaoran@gmail.com>

From: Xiaoran Wang <fanfuxiaoran@gmail.com>
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2024-08-19T06:17:17Z
Lists: pgsql-hackers

Attachments

https://www.postgresql.org/message-id/CANncwrJTse6WKkUS_Y8Wj2PHVRvaqPxMk_qtEPsf_+NVPYxzyg@mail.gmail.com

As the problem discussed in the above thread, I also run into that. Besides
updating the doc, I would like to report a error for it.

If the code in PG_TRY contains any non local control flow other than
ereport(ERROR) like goto, break etc., the PG_CATCH or PG_END_TRY cannot
be called, then the PG_exception_stack will point to the memory whose
stack frame has been released. So after that, when the pg_re_throw
called, __longjmp() will crash and report Segmentation fault error.

 In that case, to help developers to figure out the root cause easily, it is
 better to report that 'the sigjmp_buf is invalid' rather than letting
 the __longjmp report any error.

 Addition to sigjmp_buf, add another field 'int magic' which is next to
 the sigjum_buf in the local stack frame memory. The magic's value is always
 'PG_exception_magic 0x12345678'. And in 'pg_re_throw' routine, check if
 the magic's value is still '0x12345678', if not, that means the memory
 where the 'PG_exception_stack' points to has been released, and the
'sigbuf'
 must be invalid.

  The related code is in patch 0001

 ------------------------------
 I'm not sure if it is necessary to add a regress test for it. In patch
0002,  to test the
 patch can work correctly, I have added a function 'pg_re_throw_crash' in
regress.c

 create function pg_re_throw_crash()
     RETURNS void
     AS :'regresslib', 'pg_re_throw_crash'
  LANGUAGE C STRICT STABLE PARALLEL SAFE;
 create above function and run 'select pg_re_throw_crash()', then will get
the error
'FATAL:  Invalid sigjum_buf, code in PG_TRY cannot contain any non local
control flow other than ereport'

-- 
Best regards !
Xiaoran Wang