Message ID | 20211114204331.39555-2-huobean@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Two change for mmc-utils | expand |
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
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
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
> 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 --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]);