Using the return value of strlcpy() and strlcat()

Started by Dagfinn Ilmari Mannsåkerabout 7 years ago7 messageshackers
Jump to latest

Hi hackers,

Over in the "Include all columns in default names for foreign key
constraints" thread[1]/messages/by-id/CAF+2_SHzBU0tWKvJMZAXfcmrnCwJUeCrAohga0awDf9uDBptnw@mail.gmail.com -- "A disappointingly low fraction of the human race is, at any given time, on fire." - Stig Sandbeck Mathisen, I noticed the patch added the following:

+		strlcpy(buf + buflen, name, NAMEDATALEN);
+		buflen += strlen(buf + buflen);

Seeing as strlcpy() returns the copied length, this seems rather
redundant. A quick bit of grepping shows that this pattern occurs in
several places, including the ChooseIndexNameAddition and
ChooseExtendedStatisticNameAddition functions this was no doubt inspired
by.

Attached is a patch that instead uses the return value of strlcpy() and
strlcat(). I left some strlen() calls alone in places where it wasn't
convenient (e.g. pg_open_tzfile(), where it would need an extra
variable).

- ilmari

[1]: /messages/by-id/CAF+2_SHzBU0tWKvJMZAXfcmrnCwJUeCrAohga0awDf9uDBptnw@mail.gmail.com -- "A disappointingly low fraction of the human race is, at any given time, on fire." - Stig Sandbeck Mathisen
--
"A disappointingly low fraction of the human race is,
at any given time, on fire." - Stig Sandbeck Mathisen

Attachments:

0001-Use-the-return-value-of-strlcpy-and-strlcat.patchtext/x-diffDownload+12-21
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dagfinn Ilmari Mannsåker (#1)
Re: Using the return value of strlcpy() and strlcat()

ilmari@ilmari.org (Dagfinn Ilmari =?utf-8?Q?Manns=C3=A5ker?=) writes:

[ let's convert
+		strlcpy(buf + buflen, name, NAMEDATALEN);
+		buflen += strlen(buf + buflen);
to
+		buflen += strlcpy(buf + buflen, name, NAMEDATALEN);
]

I don't think that's a safe transformation: what strlcpy returns is
strlen(src), which might be different from what it was actually
able to fit into the destination.

Sure, they're equivalent if no truncation occurred; but if we were
100.00% sure of no truncation, we'd likely not bother with strlcpy.

regards, tom lane

#3Ashwin Agrawal
aagrawal@pivotal.io
In reply to: Tom Lane (#2)
Re: Using the return value of strlcpy() and strlcat()

On Wed, Mar 13, 2019 at 9:51 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

ilmari@ilmari.org (Dagfinn Ilmari =?utf-8?Q?Manns=C3=A5ker?=) writes:

[ let's convert
+             strlcpy(buf + buflen, name, NAMEDATALEN);
+             buflen += strlen(buf + buflen);
to
+             buflen += strlcpy(buf + buflen, name, NAMEDATALEN);
]

I don't think that's a safe transformation: what strlcpy returns is
strlen(src), which might be different from what it was actually
able to fit into the destination.

Sure, they're equivalent if no truncation occurred; but if we were
100.00% sure of no truncation, we'd likely not bother with strlcpy.

So, if return value < length (3rd argument) we should be able to use the
return value and avoid the strlen, else do the strlen ?

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Ashwin Agrawal (#3)
Re: Using the return value of strlcpy() and strlcat()

Ashwin Agrawal <aagrawal@pivotal.io> writes:

On Wed, Mar 13, 2019 at 9:51 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

I don't think that's a safe transformation: what strlcpy returns is
strlen(src), which might be different from what it was actually
able to fit into the destination.
Sure, they're equivalent if no truncation occurred; but if we were
100.00% sure of no truncation, we'd likely not bother with strlcpy.

So, if return value < length (3rd argument) we should be able to use the
return value and avoid the strlen, else do the strlen ?

Mmm ... if there's a way to do it that's not messy and typo-prone,
maybe. But I'm dubious that the potential gain is worth complicating
the code. The strings involved aren't usually all that long.

regards, tom lane

In reply to: Tom Lane (#4)
Re: Using the return value of strlcpy() and strlcat()

Tom Lane <tgl@sss.pgh.pa.us> writes:

Ashwin Agrawal <aagrawal@pivotal.io> writes:

On Wed, Mar 13, 2019 at 9:51 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

I don't think that's a safe transformation: what strlcpy returns is
strlen(src), which might be different from what it was actually
able to fit into the destination.

Yeah, Andrew Gierth pointed this out on IRC as well.

Sure, they're equivalent if no truncation occurred; but if we were
100.00% sure of no truncation, we'd likely not bother with strlcpy.

So, if return value < length (3rd argument) we should be able to use the
return value and avoid the strlen, else do the strlen ?

Mmm ... if there's a way to do it that's not messy and typo-prone,
maybe. But I'm dubious that the potential gain is worth complicating
the code. The strings involved aren't usually all that long.

Please consider this patch withdrawn.

- ilmari
--
"I use RMS as a guide in the same way that a boat captain would use
a lighthouse. It's good to know where it is, but you generally
don't want to find yourself in the same spot." - Tollef Fog Heen

#6David Rowley
dgrowleyml@gmail.com
In reply to: Dagfinn Ilmari Mannsåker (#5)
Re: Using the return value of strlcpy() and strlcat()

On Fri, 15 Mar 2019 at 00:11, Dagfinn Ilmari Mannsåker
<ilmari@ilmari.org> wrote:

Tom Lane <tgl@sss.pgh.pa.us> writes:

Mmm ... if there's a way to do it that's not messy and typo-prone,
maybe. But I'm dubious that the potential gain is worth complicating
the code. The strings involved aren't usually all that long.

Please consider this patch withdrawn.

Amusingly it seems the strlcpy() return value of the chars it would
have copied if it didn't run out of space is not all that useful for
us. I see exactly 2 matches of git grep "= strlcpy". The
isolation_init() one looks genuine, but the SerializeLibraryState()
looks a bit bogus. Looking at EstimateLibraryStateSpace() it seems it
estimates the exact space, so the strlcpy should never cut short, but
it does seem like a bad example to leave laying around.

We should have maybe thought a bit harder when we put that strlcpy
code into the codebase and considered if we might have been better off
inventing our own function that just returns what it did copy instead
of what it would have.

--
David Rowley http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: David Rowley (#6)
Re: Using the return value of strlcpy() and strlcat()

David Rowley <david.rowley@2ndquadrant.com> writes:

We should have maybe thought a bit harder when we put that strlcpy
code into the codebase and considered if we might have been better off
inventing our own function that just returns what it did copy instead
of what it would have.

Well, strlcpy is (somewhat) standardized; we didn't just invent it
off the cuff. I thought a little bit about whether it would be worth
having a variant version with a different return value, but concluded
that having YA strcpy variant would more likely be a dangerous source
of thinkos than something that was actually helpful. Otherwise I'd
have given Ashwin a more positive reaction...

regards, tom lane