Re: More speedups for tuple deformation

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: David Rowley <dgrowleyml(at)gmail(dot)com>
Cc: PostgreSQL Developers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: More speedups for tuple deformation
Date: 2026-01-20 04:32:55
Message-ID: 0663AA4F-74FB-48A5-B77B-3C150445FF2B@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Jan 20, 2026, at 08:11, David Rowley <dgrowleyml(at)gmail(dot)com> wrote:
>
> On Mon, 19 Jan 2026 at 18:48, Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> wrote:
>> I reviewed the patch and traced some basic workflows. But I haven’t done a load test to compare performance differences with and without this patch, I will do that if I get some bandwidth later. Here comes some review comments:
>>
>> 1 - tupmacs.h
>> ```
>> + /* Create a mask with all bits beyond natts's bit set to off */
>> + mask = 0xFF & ((((uint8) 1) << (natts & 7)) - 1);
>> + byte = (~bits[lastByte]) & mask;
>> ```
>>
>> When I read the code, I got an impression bits[lastByte] might overflow when natts % 8 == 0, so I traced the code, then I realized that, this function is only called when a row has null values, so that, when reaching here, natts % 8 != 0, otherwise it should return earlier within the for loop.
>
> It certainly is possible to get to that part of the code when natts is
> a multiple of 8 and the tuple contains NULLs after that (we may not be
> deforming the entire tuple). The code you quoted that's setting "mask"
> in that case will produce a zero mask, resulting in not finding any
> NULLs. I don't quite see any risk of overflowing any of the types
> here. If natts is 16 then effectively the code does 0xFF & ((1 << 0)
> - 1); so no overflow. Just left shift by 0 bits and bitwise AND with
> zero, resulting in the mask becoming zero.
>
> How about if I write the comment as follows?
>
> /*
> * Create a mask with all bits beyond natts's bit set to off. The code
> * below will generate a zero mask when natts & 7 == 0. When that happens
> * all bytes that need to be checked were done so in the loop above. The
> * code below will create an empty mask and end up returning natts. This
> * has been done to avoid having to write a special case to check if we've
> * covered all bytes already.
> */
>

I’m sorry I didn’t express myself clearly, maybe I should have used “OOB” rather than “overflow". My real concern is about out-of-boundary read of bits[lastByte] when natts&7==0.

Say, natts is 16, then bits is 2 bytes long; lastByte = 16>>3 = 2, so bits[2] is a OOB read.

If first_null_attr() is only called when hasnulls==true, then it will never hit the OOB point, because it will return early from the “for” loop. In the current patch, which is true, so the OOB should never happen.

However, I don’t see any comment mentions something like “first_null_attr() should only be called when hasnulls is true. If in future one calls first_null_attr() in a situation where hasnulls == false, then the OOB will be triggered.

The comment you added explains that even if OOB happens, no matter what value is hold by bits[lastByte], because mask is 0, the final result is still correct, which is true, but OOB is still a concern. If the bits array happens to end exactly at the edge of a memory page, the OOB read bits[lastByte] may trigger a segment fault; and valgrind may detect the OOB and complain about it.

So, my original comment was that, we should at least add something to the header comment to mention “first_null_attr() should only be called when hasnulls is true. If we can add an Assert to ensure hasnulls is true, that would be even better.

But if we want first_null_attr() to be safe no matter hasnulls is true or false, I think we should avoid the OOB.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message shveta malik 2026-01-20 04:43:28 Re: Simplify code building the LR conflict messages
Previous Message Michael Paquier 2026-01-20 04:29:30 Re: Extended Statistics set/restore/clear functions.