Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 299d171

Browse files
committed
Install defenses against overflow in BuildTupleHashTable().
The planner can sometimes compute very large values for numGroups, and in cases where we have no alternative to building a hashtable, such a value will get fed directly to BuildTupleHashTable as its nbuckets parameter. There were two ways in which that could go bad. First, BuildTupleHashTable declared the parameter as "int" but most callers were passing "long"s, so on 64-bit machines undetected overflow could occur leading to a bogus negative value. The obvious fix for that is to change the parameter to "long", which is what I've done in HEAD. In the back branches that seems a bit risky, though, since third-party code might be calling this function. So for them, just put in a kluge to treat negative inputs as INT_MAX. Second, hash_create can go nuts with extremely large requested table sizes (notably, my_log2 becomes an infinite loop for inputs larger than LONG_MAX/2). What seems most appropriate to avoid that is to bound the initial table size request to work_mem. This fixes bug #6035 reported by Daniel Schreiber. Although the reported case only occurs back to 8.4 since it involves WITH RECURSIVE, I think it's a good idea to install the defenses in all supported branches.
1 parent a9b6519 commit 299d171

File tree

3 files changed

+9
-5
lines changed

3 files changed

+9
-5
lines changed

src/backend/executor/execGrouping.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "postgres.h"
2020

2121
#include "executor/executor.h"
22+
#include "miscadmin.h"
2223
#include "parser/parse_oper.h"
2324
#include "utils/lsyscache.h"
2425
#include "utils/memutils.h"
@@ -276,7 +277,7 @@ TupleHashTable
276277
BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
277278
FmgrInfo *eqfunctions,
278279
FmgrInfo *hashfunctions,
279-
int nbuckets, Size entrysize,
280+
long nbuckets, Size entrysize,
280281
MemoryContext tablecxt, MemoryContext tempcxt)
281282
{
282283
TupleHashTable hashtable;
@@ -285,6 +286,9 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
285286
Assert(nbuckets > 0);
286287
Assert(entrysize >= sizeof(TupleHashEntryData));
287288

289+
/* Limit initial table size request to not more than work_mem */
290+
nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize));
291+
288292
hashtable = (TupleHashTable) MemoryContextAlloc(tablecxt,
289293
sizeof(TupleHashTableData));
290294

@@ -306,7 +310,7 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
306310
hash_ctl.hash = TupleHashTableHash;
307311
hash_ctl.match = TupleHashTableMatch;
308312
hash_ctl.hcxt = tablecxt;
309-
hashtable->hashtab = hash_create("TupleHashTable", (long) nbuckets,
313+
hashtable->hashtab = hash_create("TupleHashTable", nbuckets,
310314
&hash_ctl,
311315
HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
312316

src/backend/executor/nodeSubplan.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
432432
int ncols = list_length(subplan->paramIds);
433433
ExprContext *innerecontext = node->innerecontext;
434434
MemoryContext oldcontext;
435-
int nbuckets;
435+
long nbuckets;
436436
TupleTableSlot *slot;
437437

438438
Assert(subplan->subLinkType == ANY_SUBLINK);
@@ -458,7 +458,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
458458
node->havehashrows = false;
459459
node->havenullrows = false;
460460

461-
nbuckets = (int) ceil(planstate->plan->plan_rows);
461+
nbuckets = (long) Min(planstate->plan->plan_rows, (double) LONG_MAX);
462462
if (nbuckets < 1)
463463
nbuckets = 1;
464464

src/include/executor/executor.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ extern void execTuplesHashPrepare(int numCols,
131131
extern TupleHashTable BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
132132
FmgrInfo *eqfunctions,
133133
FmgrInfo *hashfunctions,
134-
int nbuckets, Size entrysize,
134+
long nbuckets, Size entrysize,
135135
MemoryContext tablecxt,
136136
MemoryContext tempcxt);
137137
extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable,

0 commit comments

Comments
 (0)