diff mbox series

[v1,1/2] mmc-utils: Use memcpy instead of strncpy

Message ID 20211114204331.39555-2-huobean@gmail.com (mailing list archive)
State New, archived
Headers show
Series Two change for mmc-utils | expand

Commit Message

Bean Huo Nov. 14, 2021, 8:43 p.m. UTC
From: Bean Huo <beanhuo@micron.com>

The -Wstringop-truncation warning added in GCC 8.0:
    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82944

If you use the GCC > v8.0, you probably will get this compilation error:

error: ‘__builtin_strncpy’ output may be truncated copying 8
bytes from a string of length 511 [-Werror=stringop-truncation]

Use memcpy instead of strncpy to avoid this compilation error.

Signed-off-by: Bean Huo <beanhuo@micron.com>
---
 mmc_cmds.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

Ajay Garg Nov. 15, 2021, 7:09 a.m. UTC | #1
Hi Bean.

> -               strncpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
> +               memcpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
> +               lbuf[8] = '\0';

Above copies exactly 8 bytes, without any regard to the sizes of
destination-buffer (lbuf) or source-buffer (ext_csd). Thus, there are
high chances of overflow/underflow/out-of-bounds.

If ext_csd contains, say a string 5 characters long, you would want to
copy 6 characters (5 for length, 1 for null-terminator).

I guess you are trying to copy as-many-bytes as possible to lbuf,
including the null-character.
Thus, strlcpy/strscpy should be used here.

Something like :

strlcpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], sizeof(lbuf));
or
strscpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], sizeof(lbuf));

Note that you do not need to worry about putting the null-terminator.
strlcpy/strscpy already take care of that for you.


Thanks and Regards,
Ajay
Avri Altman Nov. 15, 2021, 8:38 a.m. UTC | #2
Hi Bean,
> 
> The -Wstringop-truncation warning added in GCC 8.0:
>     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82944
> 
> If you use the GCC > v8.0, you probably will get this compilation error:
> 
> error: ‘__builtin_strncpy’ output may be truncated copying 8 bytes from a
> string of length 511 [-Werror=stringop-truncation]
> 
> Use memcpy instead of strncpy to avoid this compilation error.
> 
> Signed-off-by: Bean Huo <beanhuo@micron.com>
Looking into the link above, it say that this warning:
"... is specifically intended to highlight likely unintended uses of the strncpy function that truncate the terminating NUL charcter from the source string."

As this is not the case here, I wouldn't worry about this warning.

Thanks,
Avri

> ---
>  mmc_cmds.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/mmc_cmds.c b/mmc_cmds.c
> index 205e6e5b89f9..ecbde3937c81 100644
> --- a/mmc_cmds.c
> +++ b/mmc_cmds.c
> @@ -1835,7 +1835,8 @@ int do_read_extcsd(int nargs, char **argv)
> 
>         if (ext_csd_rev >= 7) {
>                  memset(lbuf, 0, sizeof(lbuf));
> -               strncpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
> +               memcpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
> +               lbuf[8] = '\0';
>                 printf("eMMC Firmware Version: %s\n", lbuf);
>                 printf("eMMC Life Time Estimation A
> [EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]: 0x%02x\n",
>                         ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]);
> --
> 2.25.1
Bean Huo Nov. 15, 2021, 10:49 a.m. UTC | #3
Hi Ajay,
thanks for your review.

On Mon, 2021-11-15 at 12:39 +0530, Ajay Garg wrote:
> Hi Bean.
> 
> > -               strncpy(lbuf,
> > (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
> > +               memcpy(lbuf,
> > (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
> > +               lbuf[8] = '\0';
> 
> Above copies exactly 8 bytes, without any regard to the sizes of
> destination-buffer (lbuf) or source-buffer (ext_csd). Thus, there are
> high chances of overflow/underflow/out-of-bounds.
> 
I don't understand how above memcpy() overflow/underflow/out-of-bounds?
would you please provide more specific reason? 
 
memcpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);

here lbuf is a char array lbuf[10], and ext_csd is a __u8 array, __u8
ext_csd[512]. 


> If ext_csd contains, say a string 5 characters long, you would want
> to
> copy 6 characters (5 for length, 1 for null-terminator).
> 
> I guess you are trying to copy as-many-bytes as possible to lbuf,
> including the null-character.
> Thus, strlcpy/strscpy should be used here.
> 
> Something like :
> 
> strlcpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION],
> sizeof(lbuf));
> or
> strscpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION],
> sizeof(lbuf));
> 
> Note that you do not need to worry about putting the null-terminator.
> strlcpy/strscpy already take care of that for you.
> 



Yes, but please remember that mmc-utils is mainly used for embedded
platforms, they are not easy/inconvenient to update to the latest
library to support these two APIs(strlcpy needs libbsd-dev, and strscpy
needs some one else.).  If we use strlcpy or strscpy, mmc-utils will
not be portable. Do you know any other API that can be used and make
code more portable and simpler?


Kind regards,
Bean

> 
> Thanks and Regards,
> Ajay
Ajay Garg Nov. 15, 2021, 11:37 a.m. UTC | #4
> I don't understand how above memcpy() overflow/underflow/out-of-bounds?
> would you please provide more specific reason?
>
> memcpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
>
> here lbuf is a char array lbuf[10], and ext_csd is a __u8 array, __u8
> ext_csd[512].

Ok, in the given information parameters, it might work fine at runtime.

But still, using 8 as the magic number makes the code illegible for a
third-party. Plus the code is also unoptimised, eg :

i)
If ext = "abc", then we need to copy (3 + 1) bytes.
However, currently memcpy would copy (8 + 1) bytes.

ii)
If ext = "abcdefghijklmnopqrst", then we need to copy (9 + 1) bytes.
However, currently memcpy would copy (8 + 1) bytes.


> Yes, but please remember that mmc-utils is mainly used for embedded
> platforms, they are not easy/inconvenient to update to the latest
> library to support these two APIs(strlcpy needs libbsd-dev, and strscpy
> needs some one else.).  If we use strlcpy or strscpy, mmc-utils will
> not be portable. Do you know any other API that can be used and make
> code more portable and simpler?
>

Hmm, you can always start adding code locally in your codebase.
Anyways, if you *must* use only "already available code", snprintf is
an alternative.

snprintf(lbuf, sizeof(lbuf), (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION]);
diff mbox series

Patch

diff --git a/mmc_cmds.c b/mmc_cmds.c
index 205e6e5b89f9..ecbde3937c81 100644
--- a/mmc_cmds.c
+++ b/mmc_cmds.c
@@ -1835,7 +1835,8 @@  int do_read_extcsd(int nargs, char **argv)
 
 	if (ext_csd_rev >= 7) {
                 memset(lbuf, 0, sizeof(lbuf));
-		strncpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
+		memcpy(lbuf, (char*)&ext_csd[EXT_CSD_FIRMWARE_VERSION], 8);
+		lbuf[8] = '\0';
 		printf("eMMC Firmware Version: %s\n", lbuf);
 		printf("eMMC Life Time Estimation A [EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]: 0x%02x\n",
 			ext_csd[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]);