Skip to content

Commit 17b38fa

Browse files
committed
Add support for detecting register-stack overrun on IA64.
Per recent investigation, the register stack can grow faster than the regular stack depending on compiler and choice of options. To avoid crashes we must check both stacks in check_stack_depth(). Back-patch to all supported versions.
1 parent 9f22a3f commit 17b38fa

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

src/backend/tcop/postgres.c

+59
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ static int max_stack_depth_bytes = 2048 * 1024;
9797
/* Do not make static so PL/Java can modifiy it */
9898
char *stack_base_ptr = NULL;
9999

100+
/*
101+
* On IA64 we also have to remember the register stack base.
102+
*/
103+
#if defined(__ia64__) || defined(__ia64)
104+
char *register_stack_base_ptr = NULL;
105+
#endif
100106

101107
/*
102108
* Flag to mark SIGHUP. Whenever the main loop comes around it
@@ -2288,6 +2294,35 @@ ProcessInterrupts(void)
22882294
}
22892295

22902296

2297+
/*
2298+
* IA64-specific code to fetch the AR.BSP register for stack depth checks.
2299+
*
2300+
* We currently support gcc and icc here.
2301+
*/
2302+
#if defined(__ia64__) || defined(__ia64)
2303+
2304+
#include <asm/ia64regs.h>
2305+
2306+
static __inline__ char *
2307+
ia64_get_bsp(void)
2308+
{
2309+
char *ret;
2310+
2311+
#ifndef __INTEL_COMPILER
2312+
/* the ;; is a "stop", seems to be required before fetching BSP */
2313+
__asm__ __volatile__(
2314+
";;\n"
2315+
" mov %0=ar.bsp \n"
2316+
: "=r"(ret));
2317+
#else
2318+
ret = (char *) __getReg(_IA64_REG_AR_BSP);
2319+
#endif
2320+
return ret;
2321+
}
2322+
2323+
#endif /* IA64 */
2324+
2325+
22912326
/*
22922327
* check_stack_depth: check for excessively deep recursion
22932328
*
@@ -2335,6 +2370,27 @@ check_stack_depth(void)
23352370
errmsg("stack depth limit exceeded"),
23362371
errhint("Increase the configuration parameter \"max_stack_depth\".")));
23372372
}
2373+
2374+
/*
2375+
* On IA64 there is a separate "register" stack that requires its own
2376+
* independent check. For this, we have to measure the change in the
2377+
* "BSP" pointer from PostgresMain to here. Logic is just as above,
2378+
* except that we know IA64's register stack grows up.
2379+
*
2380+
* Note we assume that the same max_stack_depth applies to both stacks.
2381+
*/
2382+
#if defined(__ia64__) || defined(__ia64)
2383+
stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr);
2384+
2385+
if (stack_depth > max_stack_depth_bytes &&
2386+
register_stack_base_ptr != NULL)
2387+
{
2388+
ereport(ERROR,
2389+
(errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
2390+
errmsg("stack depth limit exceeded"),
2391+
errhint("Increase the configuration parameter \"max_stack_depth\".")));
2392+
}
2393+
#endif /* IA64 */
23382394
}
23392395

23402396
/* GUC assign hook to update max_stack_depth_bytes from max_stack_depth */
@@ -2491,6 +2547,9 @@ PostgresMain(int argc, char *argv[], const char *username)
24912547

24922548
/* Set up reference point for stack depth checking */
24932549
stack_base_ptr = &stack_base;
2550+
#if defined(__ia64__) || defined(__ia64)
2551+
register_stack_base_ptr = ia64_get_bsp();
2552+
#endif
24942553

24952554
/* Compute paths, if we didn't inherit them from postmaster */
24962555
if (my_exec_path[0] == '\0')

0 commit comments

Comments
 (0)