diff options
Diffstat (limited to 'src/pl')
| -rw-r--r-- | src/pl/plperl/plperl.c | 25 | ||||
| -rw-r--r-- | src/pl/plpgsql/src/pl_exec.c | 20 | ||||
| -rw-r--r-- | src/pl/plpgsql/src/plpgsql.h | 2 | ||||
| -rw-r--r-- | src/pl/plpython/plpy_cursorobject.c | 18 | ||||
| -rw-r--r-- | src/pl/plpython/plpy_spi.c | 28 | ||||
| -rw-r--r-- | src/pl/tcl/pltcl.c | 19 |
6 files changed, 79 insertions, 33 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index cd917ab8e46..269f7f33220 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -12,8 +12,9 @@ /* system stuff */ #include <ctype.h> #include <fcntl.h> -#include <unistd.h> +#include <limits.h> #include <locale.h> +#include <unistd.h> /* postgreSQL stuff */ #include "access/htup_details.h" @@ -281,7 +282,7 @@ static Datum plperl_hash_to_datum(SV *src, TupleDesc td); static void plperl_init_shared_libs(pTHX); static void plperl_trusted_init(void); static void plperl_untrusted_init(void); -static HV *plperl_spi_execute_fetch_result(SPITupleTable *, int, int); +static HV *plperl_spi_execute_fetch_result(SPITupleTable *, uint64, int); static char *hek2cstr(HE *he); static SV **hv_store_string(HV *hv, const char *key, SV *val); static SV **hv_fetch_string(HV *hv, const char *key); @@ -1472,7 +1473,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid) hv = newHV(); (void) hv_store(hv, "array", 5, av, 0); - (void) hv_store(hv, "typeoid", 7, newSViv(typid), 0); + (void) hv_store(hv, "typeoid", 7, newSVuv(typid), 0); return sv_bless(newRV_noinc((SV *) hv), gv_stashpv("PostgreSQL::InServer::ARRAY", 0)); @@ -3091,7 +3092,7 @@ plperl_spi_exec(char *query, int limit) static HV * -plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed, +plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed, int status) { HV *result; @@ -3103,13 +3104,25 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed, hv_store_string(result, "status", cstr2sv(SPI_result_code_string(status))); hv_store_string(result, "processed", - newSViv(processed)); + (processed > (uint64) INT_MAX) ? + newSVnv((double) processed) : + newSViv((int) processed)); if (status > 0 && tuptable) { AV *rows; SV *row; - int i; + uint64 i; + + /* + * av_extend's 2nd argument is declared I32. It's possible we could + * nonetheless push more than INT_MAX elements into a Perl array, but + * let's just fail instead of trying. + */ + if (processed > (uint64) INT_MAX) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("query result has too many rows to fit in a Perl array"))); rows = newAV(); av_extend(rows, processed); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index bd58d5f444f..b63ecacdecf 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -1601,8 +1601,8 @@ exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt) { case PLPGSQL_GETDIAG_ROW_COUNT: exec_assign_value(estate, var, - UInt32GetDatum(estate->eval_processed), - false, INT4OID, -1); + UInt64GetDatum(estate->eval_processed), + false, INT8OID, -1); break; case PLPGSQL_GETDIAG_RESULT_OID: @@ -2856,7 +2856,7 @@ exec_stmt_return_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_return_query *stmt) { Portal portal; - uint32 processed = 0; + uint64 processed = 0; TupleConversionMap *tupmap; if (!estate->retisset) @@ -2887,7 +2887,7 @@ exec_stmt_return_query(PLpgSQL_execstate *estate, while (true) { - int i; + uint64 i; SPI_cursor_fetch(portal, true, 50); if (SPI_processed == 0) @@ -3579,7 +3579,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, if (stmt->into) { SPITupleTable *tuptab = SPI_tuptable; - uint32 n = SPI_processed; + uint64 n = SPI_processed; PLpgSQL_rec *rec = NULL; PLpgSQL_row *row = NULL; @@ -3769,7 +3769,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, if (stmt->into) { SPITupleTable *tuptab = SPI_tuptable; - uint32 n = SPI_processed; + uint64 n = SPI_processed; PLpgSQL_rec *rec = NULL; PLpgSQL_row *row = NULL; @@ -4043,7 +4043,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt) SPITupleTable *tuptab; Portal portal; char *curname; - uint32 n; + uint64 n; /* ---------- * Get the portal of the cursor by name @@ -5151,7 +5151,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, SPITupleTable *tuptab; bool found = false; int rc = PLPGSQL_RC_OK; - int n; + uint64 n; /* * Determine if we assign to a record or a row @@ -5182,7 +5182,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, * If the query didn't return any rows, set the target to NULL and fall * through with found = false. */ - if (n <= 0) + if (n == 0) { exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); exec_eval_cleanup(estate); @@ -5195,7 +5195,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, */ while (n > 0) { - int i; + uint64 i; for (i = 0; i < n; i++) { diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index a1e900d7336..2deece43eb7 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -820,7 +820,7 @@ typedef struct PLpgSQL_execstate /* temporary state for results from evaluation of query or expr */ SPITupleTable *eval_tuptable; - uint32 eval_processed; + uint64 eval_processed; Oid eval_lastoid; ExprContext *eval_econtext; /* for executing simple expressions */ diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c index 103571ba15c..44ba76e765e 100644 --- a/src/pl/plpython/plpy_cursorobject.c +++ b/src/pl/plpython/plpy_cursorobject.c @@ -6,6 +6,8 @@ #include "postgres.h" +#include <limits.h> + #include "access/xact.h" #include "mb/pg_wchar.h" #include "utils/memutils.h" @@ -446,11 +448,23 @@ PLy_cursor_fetch(PyObject *self, PyObject *args) ret->status = PyInt_FromLong(SPI_OK_FETCH); Py_DECREF(ret->nrows); - ret->nrows = PyInt_FromLong(SPI_processed); + ret->nrows = (SPI_processed > (uint64) LONG_MAX) ? + PyFloat_FromDouble((double) SPI_processed) : + PyInt_FromLong((long) SPI_processed); if (SPI_processed != 0) { - int i; + uint64 i; + + /* + * PyList_New() and PyList_SetItem() use Py_ssize_t for list size + * and list indices; so we cannot support a result larger than + * PY_SSIZE_T_MAX. + */ + if (SPI_processed > (uint64) PY_SSIZE_T_MAX) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("query result has too many rows to fit in a Python list"))); Py_DECREF(ret->rows); ret->rows = PyList_New(SPI_processed); diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c index 58e78ecebcb..7d84629f48f 100644 --- a/src/pl/plpython/plpy_spi.c +++ b/src/pl/plpython/plpy_spi.c @@ -6,6 +6,8 @@ #include "postgres.h" +#include <limits.h> + #include "access/htup_details.h" #include "access/xact.h" #include "catalog/pg_type.h" @@ -29,7 +31,8 @@ static PyObject *PLy_spi_execute_query(char *query, long limit); static PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit); -static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status); +static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable, + uint64 rows, int status); static void PLy_spi_exception_set(PyObject *excclass, ErrorData *edata); @@ -382,7 +385,7 @@ PLy_spi_execute_query(char *query, long limit) } static PyObject * -PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status) +PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status) { PLyResultObject *result; volatile MemoryContext oldcontext; @@ -394,16 +397,19 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status) if (status > 0 && tuptable == NULL) { Py_DECREF(result->nrows); - result->nrows = PyInt_FromLong(rows); + result->nrows = (rows > (uint64) LONG_MAX) ? + PyFloat_FromDouble((double) rows) : + PyInt_FromLong((long) rows); } else if (status > 0 && tuptable != NULL) { PLyTypeInfo args; - int i; MemoryContext cxt; Py_DECREF(result->nrows); - result->nrows = PyInt_FromLong(rows); + result->nrows = (rows > (uint64) LONG_MAX) ? + PyFloat_FromDouble((double) rows) : + PyInt_FromLong((long) rows); cxt = AllocSetContextCreate(CurrentMemoryContext, "PL/Python temp context", @@ -419,6 +425,18 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status) if (rows) { + uint64 i; + + /* + * PyList_New() and PyList_SetItem() use Py_ssize_t for list + * size and list indices; so we cannot support a result larger + * than PY_SSIZE_T_MAX. + */ + if (rows > (uint64) PY_SSIZE_T_MAX) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("query result has too many rows to fit in a Python list"))); + Py_DECREF(result->rows); result->rows = PyList_New(rows); diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 105b6186f64..5b27c731b6e 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -226,7 +226,7 @@ static int pltcl_process_SPI_result(Tcl_Interp *interp, Tcl_Obj *loop_body, int spi_rc, SPITupleTable *tuptable, - int ntuples); + uint64 ntuples); static int pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int pltcl_SPI_execute_plan(ClientData cdata, Tcl_Interp *interp, @@ -235,7 +235,7 @@ static int pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname, - int tupno, HeapTuple tuple, TupleDesc tupdesc); + uint64 tupno, HeapTuple tuple, TupleDesc tupdesc); static Tcl_Obj *pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc); @@ -481,7 +481,7 @@ pltcl_init_load_unknown(Tcl_Interp *interp) int tcl_rc; Tcl_DString unknown_src; char *part; - int i; + uint64 i; int fno; /************************************************************ @@ -2007,10 +2007,9 @@ pltcl_process_SPI_result(Tcl_Interp *interp, Tcl_Obj *loop_body, int spi_rc, SPITupleTable *tuptable, - int ntuples) + uint64 ntuples) { int my_rc = TCL_OK; - int i; int loop_rc; HeapTuple *tuples; TupleDesc tupdesc; @@ -2021,7 +2020,7 @@ pltcl_process_SPI_result(Tcl_Interp *interp, case SPI_OK_INSERT: case SPI_OK_DELETE: case SPI_OK_UPDATE: - Tcl_SetObjResult(interp, Tcl_NewIntObj(ntuples)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(ntuples)); break; case SPI_OK_UTILITY: @@ -2060,6 +2059,8 @@ pltcl_process_SPI_result(Tcl_Interp *interp, * There is a loop body - process all tuples and evaluate the * body on each */ + uint64 i; + for (i = 0; i < ntuples; i++) { pltcl_set_tuple_values(interp, arrayname, i, @@ -2085,7 +2086,7 @@ pltcl_process_SPI_result(Tcl_Interp *interp, if (my_rc == TCL_OK) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(ntuples)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(ntuples)); } break; @@ -2472,7 +2473,7 @@ pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp, **********************************************************************/ static void pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname, - int tupno, HeapTuple tuple, TupleDesc tupdesc) + uint64 tupno, HeapTuple tuple, TupleDesc tupdesc) { int i; char *outputstr; @@ -2498,7 +2499,7 @@ pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname, { arrptr = &arrayname; nameptr = &attname; - Tcl_SetVar2Ex(interp, arrayname, ".tupno", Tcl_NewIntObj(tupno), 0); + Tcl_SetVar2Ex(interp, arrayname, ".tupno", Tcl_NewWideIntObj(tupno), 0); } for (i = 0; i < tupdesc->natts; i++) |
