/* * MaxAllocSize, MaxAllocHugeSize * Quasi-arbitrary limits on size of allocations. * * Note: * There is no guarantee that smaller allocations will succeed, but * larger requests will be summarily denied. * * palloc() enforces MaxAllocSize, chosen to correspond to the limiting size * of varlena objects under TOAST. See VARSIZE_4B() and related macros in * postgres.h. Many datatypes assume that any allocatable size can be * represented in a varlena header. This limit also permits a caller to use * an "int" variable for an index into or length of an allocation. Callers * careful to avoid these hazards can access the higher limit with * MemoryContextAllocHuge(). Both limits permit code to assume that it may * compute twice an allocation's size without overflow. */ #define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
Datum repeat(PG_FUNCTION_ARGS) { text *string = PG_GETARG_TEXT_PP(0); int32 count = PG_GETARG_INT32(1); text *result; int slen, tlen; int i; char *cp, *sp;
if (count < 0) count = 0;
slen = VARSIZE_ANY_EXHDR(string);
if (unlikely(pg_mul_s32_overflow(count, slen, &tlen)) || unlikely(pg_add_s32_overflow(tlen, VARHDRSZ, &tlen))) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested length too large")));
result = (text *) palloc(tlen);
SET_VARSIZE(result, tlen); cp = VARDATA(result); sp = VARDATA_ANY(string); for (i = 0; i < count; i++) { memcpy(cp, sp, slen); cp += slen; CHECK_FOR_INTERRUPTS(); }
/* * Allocate and zero the space needed. Note that the tuple body and * HeapTupleData management structure are allocated in one chunk. */ tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
/* * Prepare a DataRow message (note buffer is in per-row context) */ pq_beginmessage_reuse(buf, 'D');
pq_sendint16(buf, natts);
/* * send the attributes of this tuple */ for (i = 0; i < natts; ++i) { PrinttupAttrInfo *thisState = myState->myinfo + i; Datum attr = slot->tts_values[i];
if (slot->tts_isnull[i]) { pq_sendint32(buf, -1); continue; }
/* * Here we catch undefined bytes in datums that are returned to the * client without hitting disk; see comments at the related check in * PageAddItem(). This test is most useful for uncompressed, * non-external datums, but we're quite likely to see such here when * testing new C functions. */ if (thisState->typisvarlena) VALGRIND_CHECK_MEM_IS_DEFINED(DatumGetPointer(attr), VARSIZE_ANY(attr)); if (thisState->format == 0) { /* Text output */ char *outputstr;