lp_offset + lp_len <= raw_page_size)
{
HeapTupleHeader tuphdr;
- bytea *tuple_data_bytea;
- int tuple_data_len;
/* Extract information from the tuple header */
-
tuphdr = (HeapTupleHeader) PageGetItem(page, id);
values[4] = UInt32GetDatum(HeapTupleHeaderGetRawXmin(tuphdr));
values[9] = UInt32GetDatum(tuphdr->t_infomask);
values[10] = UInt8GetDatum(tuphdr->t_hoff);
- /* Copy raw tuple data into bytea attribute */
- tuple_data_len = lp_len - tuphdr->t_hoff;
- tuple_data_bytea = (bytea *) palloc(tuple_data_len + VARHDRSZ);
- SET_VARSIZE(tuple_data_bytea, tuple_data_len + VARHDRSZ);
- memcpy(VARDATA(tuple_data_bytea), (char *) tuphdr + tuphdr->t_hoff,
- tuple_data_len);
- values[13] = PointerGetDatum(tuple_data_bytea);
-
/*
* We already checked that the item is completely within the raw
* page passed to us, with the length given in the line pointer.
- * Let's check that t_hoff doesn't point over lp_len, before using
- * it to access t_bits and oid.
+ * But t_hoff could be out of range, so check it before relying on
+ * it to fetch additional info.
*/
if (tuphdr->t_hoff >= SizeofHeapTupleHeader &&
tuphdr->t_hoff <= lp_len &&
tuphdr->t_hoff == MAXALIGN(tuphdr->t_hoff))
{
+ int tuple_data_len;
+ bytea *tuple_data_bytea;
+
+ /* Copy null bitmask and OID, if present */
if (tuphdr->t_infomask & HEAP_HASNULL)
{
- int bits_len;
-
- bits_len =
- BITMAPLEN(HeapTupleHeaderGetNatts(tuphdr)) * BITS_PER_BYTE;
- values[11] = CStringGetTextDatum(bits_to_text(tuphdr->t_bits, bits_len));
+ int bitmaplen;
+
+ bitmaplen = BITMAPLEN(HeapTupleHeaderGetNatts(tuphdr));
+ /* better range-check the attribute count, too */
+ if (bitmaplen <= tuphdr->t_hoff - SizeofHeapTupleHeader)
+ values[11] =
+ CStringGetTextDatum(bits_to_text(tuphdr->t_bits,
+ bitmaplen * BITS_PER_BYTE));
+ else
+ nulls[11] = true;
}
else
nulls[11] = true;
values[12] = HeapTupleHeaderGetOidOld(tuphdr);
else
nulls[12] = true;
+
+ /* Copy raw tuple data into bytea attribute */
+ tuple_data_len = lp_len - tuphdr->t_hoff;
+ tuple_data_bytea = (bytea *) palloc(tuple_data_len + VARHDRSZ);
+ SET_VARSIZE(tuple_data_bytea, tuple_data_len + VARHDRSZ);
+ if (tuple_data_len > 0)
+ memcpy(VARDATA(tuple_data_bytea),
+ (char *) tuphdr + tuphdr->t_hoff,
+ tuple_data_len);
+ values[13] = PointerGetDatum(tuple_data_bytea);
}
else
{
nulls[11] = true;
nulls[12] = true;
+ nulls[13] = true;
}
}
else