Improve conversions from uint64 to Perl types.

Perl's integers are pointer-sized, so can hold more than INT_MAX on LP64
platforms, and come in both signed (IV) and unsigned (UV).  Floating
point values (NV) may also be larger than double.

Since Perl 5.19.4 array indices are SSize_t instead of I32, so allow up
to SSize_t_max on those versions.  The limit is not imposed just by
av_extend's argument type, but all the array handling code, so remove
the speculative comment.

Dagfinn Ilmari Mannsåker
This commit is contained in:
Tom Lane 2016-03-14 14:38:36 -04:00
parent 6be84eeb8d
commit f3f3aae4b7
2 changed files with 12 additions and 9 deletions

View File

@ -3104,9 +3104,9 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed,
hv_store_string(result, "status",
cstr2sv(SPI_result_code_string(status)));
hv_store_string(result, "processed",
(processed > (uint64) INT_MAX) ?
newSVnv((double) processed) :
newSViv((int) processed));
(processed > (uint64) UV_MAX) ?
newSVnv((NV) processed) :
newSVuv((UV) processed));
if (status > 0 && tuptable)
{
@ -3114,12 +3114,8 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed,
SV *row;
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)
/* Prevent overflow in call to av_extend() */
if (processed > (uint64) AV_SIZE_MAX)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("query result has too many rows to fit in a Perl array")));

View File

@ -88,6 +88,13 @@
#define GvCV_set(gv, cv) (GvCV(gv) = cv)
#endif
/* Perl 5.19.4 changed array indices from I32 to SSize_t */
#if PERL_BCDVERSION >= 0x5019004
#define AV_SIZE_MAX SSize_t_MAX
#else
#define AV_SIZE_MAX I32_MAX
#endif
/* declare routines from plperl.c for access by .xs files */
HV *plperl_spi_exec(char *, int);
void plperl_return_next(SV *);