Skip to content

Commit b9d232b

Browse files
committed
Use "ssize_t" not "long" in max_stack_depth-related code.
This change adapts these functions to the machine's address width without depending on "long" to be the right size. (It isn't on Win64, for example.) While it seems unlikely anyone would care to run with a stack depth limit exceeding 2GB, this is part of a general push to avoid using type "long" to represent memory sizes. It's convenient to use ssize_t rather than the perhaps-more-obvious choice of size_t/Size, because the code involved depends on working with a signed data type. Our MAX_KILOBYTES limit already ensures that ssize_t will be sufficient to represent the maximum value of max_stack_depth. Extracted from a larger patch by Vladlen, plus additional hackery by me. Author: Vladlen Popolitov <v.popolitov@postgrespro.ru> Author: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/1a01f0-66ec2d80-3b-68487680@27595217
1 parent b9aa416 commit b9d232b

File tree

3 files changed

+22
-18
lines changed

3 files changed

+22
-18
lines changed

src/backend/utils/misc/guc.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ static void
15891589
InitializeGUCOptionsFromEnvironment(void)
15901590
{
15911591
char *env;
1592-
long stack_rlimit;
1592+
ssize_t stack_rlimit;
15931593

15941594
env = getenv("PGPORT");
15951595
if (env != NULL)
@@ -1613,7 +1613,7 @@ InitializeGUCOptionsFromEnvironment(void)
16131613
stack_rlimit = get_stack_depth_rlimit();
16141614
if (stack_rlimit > 0)
16151615
{
1616-
long new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L;
1616+
ssize_t new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024;
16171617

16181618
if (new_limit > 100)
16191619
{
@@ -1627,7 +1627,7 @@ InitializeGUCOptionsFromEnvironment(void)
16271627
new_limit = 2048;
16281628
source = PGC_S_DYNAMIC_DEFAULT;
16291629
}
1630-
snprintf(limbuf, sizeof(limbuf), "%ld", new_limit);
1630+
snprintf(limbuf, sizeof(limbuf), "%d", (int) new_limit);
16311631
SetConfigOption("max_stack_depth", limbuf,
16321632
PGC_POSTMASTER, source);
16331633
}

src/backend/utils/misc/stack_depth.c

+17-13
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
int max_stack_depth = 100;
2727

2828
/* max_stack_depth converted to bytes for speed of checking */
29-
static long max_stack_depth_bytes = 100 * 1024L;
29+
static ssize_t max_stack_depth_bytes = 100 * (ssize_t) 1024;
3030

3131
/*
3232
* Stack base pointer -- initialized by set_stack_base(), which
@@ -109,12 +109,12 @@ bool
109109
stack_is_too_deep(void)
110110
{
111111
char stack_top_loc;
112-
long stack_depth;
112+
ssize_t stack_depth;
113113

114114
/*
115115
* Compute distance from reference point to my local variables
116116
*/
117-
stack_depth = (long) (stack_base_ptr - &stack_top_loc);
117+
stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
118118

119119
/*
120120
* Take abs value, since stacks grow up on some machines, down on others
@@ -141,13 +141,13 @@ stack_is_too_deep(void)
141141
bool
142142
check_max_stack_depth(int *newval, void **extra, GucSource source)
143143
{
144-
long newval_bytes = *newval * 1024L;
145-
long stack_rlimit = get_stack_depth_rlimit();
144+
ssize_t newval_bytes = *newval * (ssize_t) 1024;
145+
ssize_t stack_rlimit = get_stack_depth_rlimit();
146146

147147
if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP)
148148
{
149-
GUC_check_errdetail("\"max_stack_depth\" must not exceed %ldkB.",
150-
(stack_rlimit - STACK_DEPTH_SLOP) / 1024L);
149+
GUC_check_errdetail("\"max_stack_depth\" must not exceed %zdkB.",
150+
(stack_rlimit - STACK_DEPTH_SLOP) / 1024);
151151
GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent.");
152152
return false;
153153
}
@@ -158,7 +158,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
158158
void
159159
assign_max_stack_depth(int newval, void *extra)
160160
{
161-
long newval_bytes = newval * 1024L;
161+
ssize_t newval_bytes = newval * (ssize_t) 1024;
162162

163163
max_stack_depth_bytes = newval_bytes;
164164
}
@@ -167,12 +167,16 @@ assign_max_stack_depth(int newval, void *extra)
167167
* Obtain platform stack depth limit (in bytes)
168168
*
169169
* Return -1 if unknown
170+
*
171+
* Note: we choose to use ssize_t not size_t as the result type because
172+
* callers compute values that could theoretically go negative,
173+
* such as "result - STACK_DEPTH_SLOP".
170174
*/
171-
long
175+
ssize_t
172176
get_stack_depth_rlimit(void)
173177
{
174178
#if defined(HAVE_GETRLIMIT)
175-
static long val = 0;
179+
static ssize_t val = 0;
176180

177181
/* This won't change after process launch, so check just once */
178182
if (val == 0)
@@ -182,10 +186,10 @@ get_stack_depth_rlimit(void)
182186
if (getrlimit(RLIMIT_STACK, &rlim) < 0)
183187
val = -1;
184188
else if (rlim.rlim_cur == RLIM_INFINITY)
185-
val = LONG_MAX;
189+
val = SSIZE_MAX;
186190
/* rlim_cur is probably of an unsigned type, so check for overflow */
187-
else if (rlim.rlim_cur >= LONG_MAX)
188-
val = LONG_MAX;
191+
else if (rlim.rlim_cur >= SSIZE_MAX)
192+
val = SSIZE_MAX;
189193
else
190194
val = rlim.rlim_cur;
191195
}

src/include/miscadmin.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -293,15 +293,15 @@ extern PGDLLIMPORT bool VacuumCostActive;
293293
extern PGDLLIMPORT int max_stack_depth;
294294

295295
/* Required daylight between max_stack_depth and the kernel limit, in bytes */
296-
#define STACK_DEPTH_SLOP (512 * 1024L)
296+
#define STACK_DEPTH_SLOP (512 * 1024)
297297

298298
typedef char *pg_stack_base_t;
299299

300300
extern pg_stack_base_t set_stack_base(void);
301301
extern void restore_stack_base(pg_stack_base_t base);
302302
extern void check_stack_depth(void);
303303
extern bool stack_is_too_deep(void);
304-
extern long get_stack_depth_rlimit(void);
304+
extern ssize_t get_stack_depth_rlimit(void);
305305

306306
/* in tcop/utility.c */
307307
extern void PreventCommandIfReadOnly(const char *cmdname);

0 commit comments

Comments
 (0)