diff options
author | Cong Ding <dinggnu@gmail.com> | 2013-01-25 17:48:59 -0600 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2013-01-25 17:48:59 -0600 |
commit | 1ec3911dbd19076bcdfe5540096ff67f91a6ec02 (patch) | |
tree | 95aac4248cb875f7e3f99b1373fdea5ada061298 | |
parent | c04306471ad93f1daf60771a0373316d4c3494ae (diff) | |
download | linux-3.10-1ec3911dbd19076bcdfe5540096ff67f91a6ec02.tar.gz linux-3.10-1ec3911dbd19076bcdfe5540096ff67f91a6ec02.tar.bz2 linux-3.10-1ec3911dbd19076bcdfe5540096ff67f91a6ec02.zip |
libceph: fix undefined behavior when using snprintf()
The variable "str" is used as both the source and destination in
function snprintf(), which is undefined behavior based on C11. The
original description in C11 is:
"If copying takes place between objects that
overlap, the behavior is undefined."
And, the function of ceph_osdmap_state_str() is to return the osdmap
state, so it should return "doesn't exist" when all the conditions
are not satisfied. I fix it in this patch.
[elder@inktank.com: shortened the commit message]
Signed-off-by: Cong Ding <dinggnu@gmail.com>
Reviewed-by: Alex Elder <elder@inktank.com>
-rw-r--r-- | net/ceph/osdmap.c | 28 |
1 files changed, 10 insertions, 18 deletions
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 369f03ba9ee..3c61e21611d 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -13,26 +13,18 @@ char *ceph_osdmap_state_str(char *str, int len, int state) { - int flag = 0; - if (!len) - goto done; - - *str = '\0'; - if (state) { - if (state & CEPH_OSD_EXISTS) { - snprintf(str, len, "exists"); - flag = 1; - } - if (state & CEPH_OSD_UP) { - snprintf(str, len, "%s%s%s", str, (flag ? ", " : ""), - "up"); - flag = 1; - } - } else { + return str; + + if ((state & CEPH_OSD_EXISTS) && (state & CEPH_OSD_UP)) + snprintf(str, len, "exists, up"); + else if (state & CEPH_OSD_EXISTS) + snprintf(str, len, "exists"); + else if (state & CEPH_OSD_UP) + snprintf(str, len, "up"); + else snprintf(str, len, "doesn't exist"); - } -done: + return str; } |