* git 1.9.0 segfault @ 2014-03-08 16:23 Guillaume Gelin 2014-03-08 16:46 ` brian m. carlson 0 siblings, 1 reply; 21+ messages in thread From: Guillaume Gelin @ 2014-03-08 16:23 UTC (permalink / raw) To: git Hi, http://pastebin.com/Np7L54ar Cheers, -- Guillaume Gelin ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: git 1.9.0 segfault 2014-03-08 16:23 git 1.9.0 segfault Guillaume Gelin @ 2014-03-08 16:46 ` brian m. carlson 2014-03-08 18:12 ` John Keeping 0 siblings, 1 reply; 21+ messages in thread From: brian m. carlson @ 2014-03-08 16:46 UTC (permalink / raw) To: Guillaume Gelin; +Cc: git [-- Attachment #1: Type: text/plain, Size: 2610 bytes --] On Sat, Mar 08, 2014 at 04:23:43PM +0000, Guillaume Gelin wrote: > Hi, > > http://pastebin.com/Np7L54ar I can confirm this. I get the following backtrace: Core was generated by `/home/bmc/checkouts/git/git mv packages/ lisp'. Program terminated with signal 11, Segmentation fault. #0 0x00007fe31a4371b2 in _IO_vfprintf_internal (s=s@entry=0x7fffa330d2e0, format=<optimized out>, format@entry=0x7fffa330e5b0 "renaming '%s' failed: Bad address", ap=ap@entry=0x7fffa330e498) at vfprintf.c:1649 1649 vfprintf.c: No such file or directory. (gdb) bt #0 0x00007fe31a4371b2 in _IO_vfprintf_internal (s=s@entry=0x7fffa330d2e0, format=<optimized out>, format@entry=0x7fffa330e5b0 "renaming '%s' failed: Bad address", ap=ap@entry=0x7fffa330e498) at vfprintf.c:1649 #1 0x00007fe31a4e2315 in ___vsnprintf_chk (s=s@entry=0x7fffa330d450 "renaming '0\243\377\177", maxlen=<optimized out>, maxlen@entry=4096, flags=flags@entry=1, slen=slen@entry=4096, format=0x7fffa330e5b0 "renaming '%s' failed: Bad address", format@entry=0x544fe5 "fatal: ", args=0x7fffa330e498) at vsnprintf_chk.c:63 #2 0x00000000005041cb in vsnprintf (__ap=<optimized out>, __fmt=0x544fe5 "fatal: ", __n=4096, __s=0x7fffa330d450 "renaming '0\243\377\177") at /usr/include/x86_64-linux-gnu/bits/stdio2.h:77 #3 vreportf (prefix=prefix@entry=0x544fe5 "fatal: ", err=<optimized out>, params=<optimized out>) at usage.c:12 #4 0x0000000000504224 in die_builtin (err=<optimized out>, params=<optimized out>) at usage.c:36 #5 0x0000000000504650 in die_errno (fmt=0x52be9a "renaming '%s' failed") at usage.c:137 #6 0x000000000044cb4d in cmd_mv (argc=<optimized out>, argv=<optimized out>, prefix=<optimized out>) at builtin/mv.c:246 #7 0x000000000040602d in run_builtin (argv=0x7fffa330ef90, argc=3, p=0x779d40 <commands+1536>) at git.c:314 #8 handle_builtin (argc=3, argv=0x7fffa330ef90) at git.c:487 #9 0x00000000004052e1 in run_argv (argv=0x7fffa330ee48, argcp=0x7fffa330ee2c) at git.c:533 #10 main (argc=3, av=<optimized out>) at git.c:616 We're failing to rename because we got an EFAULT, and then we try to print the failing filename, and we get a segfault right here: if (rename(src, dst) < 0 && !ignore_errors) die_errno (_("renaming '%s' failed"), src); I don't know yet if dst is also bad, but clearly src is. I'm looking into it. -- brian m. carlson / brian with sandals: Houston, Texas, US +1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187 [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: git 1.9.0 segfault 2014-03-08 16:46 ` brian m. carlson @ 2014-03-08 18:12 ` John Keeping 2014-03-08 18:35 ` [PATCH] builtin/mv: fix out of bounds write John Keeping 0 siblings, 1 reply; 21+ messages in thread From: John Keeping @ 2014-03-08 18:12 UTC (permalink / raw) To: Guillaume Gelin, git On Sat, Mar 08, 2014 at 04:46:51PM +0000, brian m. carlson wrote: > On Sat, Mar 08, 2014 at 04:23:43PM +0000, Guillaume Gelin wrote: > > Hi, > > > > http://pastebin.com/Np7L54ar > We're failing to rename because we got an EFAULT, and then we try to > print the failing filename, and we get a segfault right here: > > if (rename(src, dst) < 0 && !ignore_errors) > die_errno (_("renaming '%s' failed"), src); > > I don't know yet if dst is also bad, but clearly src is. I'm looking > into it. The problem seems to be that we change argc when we append nested directories to the list and then continue looping over 'source' which has been realloc'd to be larger. But we do not realloc submodule_gitfile at the same time so we start writing beyond the end of the submodule_gitfile array. The particular behaviour of glibc's malloc happens to mean (at least on my system) that this starts overwriting 'src'. This fixes it for me: -- >8 -- diff --git a/builtin/mv.c b/builtin/mv.c index 7e26eb5..23f119a 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -180,6 +180,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix) modes = xrealloc(modes, (argc + last - first) * sizeof(enum update_mode)); + submodule_gitfile = xrealloc(submodule_gitfile, + (argc + last - first) + * sizeof(char *)); } dst = add_slash(dst); ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH] builtin/mv: fix out of bounds write 2014-03-08 18:12 ` John Keeping @ 2014-03-08 18:35 ` John Keeping 2014-03-08 19:15 ` brian m. carlson 2014-03-08 19:21 ` [PATCH] mv: prevent mismatched data when ignoring errors brian m. carlson 0 siblings, 2 replies; 21+ messages in thread From: John Keeping @ 2014-03-08 18:35 UTC (permalink / raw) To: Junio C Hamano; +Cc: brian m. carlson, Guillaume Gelin, git, Jens Lehmann When commit a88c915 (mv: move submodules using a gitfile, 2013-07-30) added the submodule_gitfile array, it was not added to the block that enlarges the arrays when we are moving a directory so that we do not have to worry about it being a directory when we perform the actual move. After this, the loop continues over the enlarged set of sources. Since we assume that submodule_gitfile has size argc, if any of the items in the source directory are submodules we are guaranteed to write beyond the end of submodule_gitfile. Fix this by realloc'ing submodule_gitfile at the same time as the other arrays. Reported-by: Guillaume Gelin <contact@ramnes.eu> Signed-off-by: John Keeping <john@keeping.me.uk> --- On Sat, Mar 08, 2014 at 06:12:18PM +0000, John Keeping wrote: > This fixes it for me: Here it is as a proper patch. builtin/mv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builtin/mv.c b/builtin/mv.c index 21c46d1..f99c91e 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -179,6 +179,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix) modes = xrealloc(modes, (argc + last - first) * sizeof(enum update_mode)); + submodule_gitfile = xrealloc(submodule_gitfile, + (argc + last - first) + * sizeof(char *)); } dst = add_slash(dst); -- 1.9.0.6.g037df60.dirty ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH] builtin/mv: fix out of bounds write 2014-03-08 18:35 ` [PATCH] builtin/mv: fix out of bounds write John Keeping @ 2014-03-08 19:15 ` brian m. carlson 2014-03-08 19:29 ` [PATCH v2] " John Keeping 2014-03-08 19:21 ` [PATCH] mv: prevent mismatched data when ignoring errors brian m. carlson 1 sibling, 1 reply; 21+ messages in thread From: brian m. carlson @ 2014-03-08 19:15 UTC (permalink / raw) To: John Keeping; +Cc: Junio C Hamano, Guillaume Gelin, git, Jens Lehmann [-- Attachment #1: Type: text/plain, Size: 1887 bytes --] On Sat, Mar 08, 2014 at 06:35:01PM +0000, John Keeping wrote: > When commit a88c915 (mv: move submodules using a gitfile, 2013-07-30) > added the submodule_gitfile array, it was not added to the block that > enlarges the arrays when we are moving a directory so that we do not > have to worry about it being a directory when we perform the actual > move. After this, the loop continues over the enlarged set of sources. > > Since we assume that submodule_gitfile has size argc, if any of the > items in the source directory are submodules we are guaranteed to write > beyond the end of submodule_gitfile. > > Fix this by realloc'ing submodule_gitfile at the same time as the other > arrays. > > Reported-by: Guillaume Gelin <contact@ramnes.eu> > Signed-off-by: John Keeping <john@keeping.me.uk> > --- > On Sat, Mar 08, 2014 at 06:12:18PM +0000, John Keeping wrote: > > This fixes it for me: > > Here it is as a proper patch. > > builtin/mv.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/builtin/mv.c b/builtin/mv.c > index 21c46d1..f99c91e 100644 > --- a/builtin/mv.c > +++ b/builtin/mv.c > @@ -179,6 +179,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix) > modes = xrealloc(modes, > (argc + last - first) > * sizeof(enum update_mode)); > + submodule_gitfile = xrealloc(submodule_gitfile, > + (argc + last - first) > + * sizeof(char *)); > } > > dst = add_slash(dst); Yup, that's the same conclusion I came to. There are also two cases where we don't shrink the array properly. I'll rebase my patch on top of this one and send it. -- brian m. carlson / brian with sandals: Houston, Texas, US +1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187 [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2] builtin/mv: fix out of bounds write 2014-03-08 19:15 ` brian m. carlson @ 2014-03-08 19:29 ` John Keeping 0 siblings, 0 replies; 21+ messages in thread From: John Keeping @ 2014-03-08 19:29 UTC (permalink / raw) To: brian m. carlson; +Cc: Junio C Hamano, Guillaume Gelin, git, Jens Lehmann When commit a88c915 (mv: move submodules using a gitfile, 2013-07-30) added the submodule_gitfile array, it was not added to the block that enlarges the arrays when we are moving a directory so that we do not have to worry about it being a directory when we perform the actual move. After this, the loop continues over the enlarged set of sources. Since we assume that submodule_gitfile has size argc, if any of the items in the source directory are submodules we are guaranteed to write beyond the end of submodule_gitfile. Fix this by realloc'ing submodule_gitfile at the same time as the other arrays. Reported-by: Guillaume Gelin <contact@ramnes.eu> Signed-off-by: John Keeping <john@keeping.me.uk> --- On Sat, Mar 08, 2014 at 07:15:42PM +0000, brian m. carlson wrote: > Yup, that's the same conclusion I came to. There are also two cases > where we don't shrink the array properly. I'll rebase my patch on top > of this one and send it. Nice catch. While looking at that, I spotted that I forgot to initialize the new values in submodule_gitfile when it grows. Guillaume's test case doesn't catch that because all the subdirectories are submodules. builtin/mv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builtin/mv.c b/builtin/mv.c index 21c46d1..5258077 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -179,6 +179,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix) modes = xrealloc(modes, (argc + last - first) * sizeof(enum update_mode)); + submodule_gitfile = xrealloc(submodule_gitfile, + (argc + last - first) + * sizeof(char *)); } dst = add_slash(dst); @@ -192,6 +195,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix) prefix_path(dst, dst_len, path + length + 1); modes[argc + j] = INDEX; + submodule_gitfile[argc + j] = NULL; } argc += last - first; } -- 1.9.0.6.g037df60.dirty ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-08 18:35 ` [PATCH] builtin/mv: fix out of bounds write John Keeping 2014-03-08 19:15 ` brian m. carlson @ 2014-03-08 19:21 ` brian m. carlson 2014-03-11 1:56 ` Jeff King ` (3 more replies) 1 sibling, 4 replies; 21+ messages in thread From: brian m. carlson @ 2014-03-08 19:21 UTC (permalink / raw) To: git; +Cc: Jens Lehmann, John Keeping, Junio C Hamano, Guillaume Gelin We shrink the source and destination arrays, but not the modes or submodule_gitfile arrays, resulting in potentially mismatched data. Shrink all the arrays at the same time to prevent this. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> --- builtin/mv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/builtin/mv.c b/builtin/mv.c index f99c91e..b20cd95 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) memmove(destination + i, destination + i + 1, (argc - i) * sizeof(char *)); + memmove(modes + i, modes + i + 1, + (argc - i) * sizeof(char *)); + memmove(submodule_gitfile + i, + submodule_gitfile + i + 1, + (argc - i) * sizeof(char *)); i--; } } else -- 1.9.0.1010.g6633b85.dirty ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-08 19:21 ` [PATCH] mv: prevent mismatched data when ignoring errors brian m. carlson @ 2014-03-11 1:56 ` Jeff King 2014-03-11 2:00 ` brian m. carlson 2014-03-11 21:45 ` Junio C Hamano ` (2 subsequent siblings) 3 siblings, 1 reply; 21+ messages in thread From: Jeff King @ 2014-03-11 1:56 UTC (permalink / raw) To: brian m. carlson Cc: git, Jens Lehmann, John Keeping, Junio C Hamano, Guillaume Gelin On Sat, Mar 08, 2014 at 07:21:39PM +0000, brian m. carlson wrote: > We shrink the source and destination arrays, but not the modes or > submodule_gitfile arrays, resulting in potentially mismatched data. Shrink > all the arrays at the same time to prevent this. > > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > --- > builtin/mv.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/builtin/mv.c b/builtin/mv.c > index f99c91e..b20cd95 100644 > --- a/builtin/mv.c > +++ b/builtin/mv.c > @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) > memmove(destination + i, > destination + i + 1, > (argc - i) * sizeof(char *)); > + memmove(modes + i, modes + i + 1, > + (argc - i) * sizeof(char *)); > + memmove(submodule_gitfile + i, > + submodule_gitfile + i + 1, > + (argc - i) * sizeof(char *)); I haven't looked that closely, but would it be crazy to suggest that these arrays all be squashed into one array-of-struct? It would be less error prone and perhaps more readable. -Peff ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-11 1:56 ` Jeff King @ 2014-03-11 2:00 ` brian m. carlson 0 siblings, 0 replies; 21+ messages in thread From: brian m. carlson @ 2014-03-11 2:00 UTC (permalink / raw) To: Jeff King Cc: git, Jens Lehmann, John Keeping, Junio C Hamano, Guillaume Gelin [-- Attachment #1: Type: text/plain, Size: 1714 bytes --] On Mon, Mar 10, 2014 at 09:56:03PM -0400, Jeff King wrote: > On Sat, Mar 08, 2014 at 07:21:39PM +0000, brian m. carlson wrote: > > > We shrink the source and destination arrays, but not the modes or > > submodule_gitfile arrays, resulting in potentially mismatched data. Shrink > > all the arrays at the same time to prevent this. > > > > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > > --- > > builtin/mv.c | 5 +++++ > > 1 file changed, 5 insertions(+) > > > > diff --git a/builtin/mv.c b/builtin/mv.c > > index f99c91e..b20cd95 100644 > > --- a/builtin/mv.c > > +++ b/builtin/mv.c > > @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) > > memmove(destination + i, > > destination + i + 1, > > (argc - i) * sizeof(char *)); > > + memmove(modes + i, modes + i + 1, > > + (argc - i) * sizeof(char *)); > > + memmove(submodule_gitfile + i, > > + submodule_gitfile + i + 1, > > + (argc - i) * sizeof(char *)); > > I haven't looked that closely, but would it be crazy to suggest that > these arrays all be squashed into one array-of-struct? It would be less > error prone and perhaps more readable. I was thinking of doing exactly that, but the way internal_copy_pathspec is written, I'd need to use offsetof to have it write to the right structure members. That's a bit more gross than I wanted, but I'll probably implement it at some point during the upcoming week. -- brian m. carlson / brian with sandals: Houston, Texas, US +1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187 [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-08 19:21 ` [PATCH] mv: prevent mismatched data when ignoring errors brian m. carlson 2014-03-11 1:56 ` Jeff King @ 2014-03-11 21:45 ` Junio C Hamano 2014-03-12 23:21 ` brian m. carlson 2014-03-15 16:05 ` Thomas Rast 2014-03-15 18:56 ` [PATCH v2] " brian m. carlson 3 siblings, 1 reply; 21+ messages in thread From: Junio C Hamano @ 2014-03-11 21:45 UTC (permalink / raw) To: brian m. carlson; +Cc: git, Jens Lehmann, John Keeping, Guillaume Gelin "brian m. carlson" <sandals@crustytoothpaste.net> writes: > We shrink the source and destination arrays, but not the modes or > submodule_gitfile arrays, resulting in potentially mismatched data. Shrink > all the arrays at the same time to prevent this. > > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > --- > builtin/mv.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/builtin/mv.c b/builtin/mv.c > index f99c91e..b20cd95 100644 > --- a/builtin/mv.c > +++ b/builtin/mv.c > @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) > memmove(destination + i, > destination + i + 1, > (argc - i) * sizeof(char *)); > + memmove(modes + i, modes + i + 1, > + (argc - i) * sizeof(char *)); > + memmove(submodule_gitfile + i, > + submodule_gitfile + i + 1, > + (argc - i) * sizeof(char *)); > i--; > } > } else Thanks. Neither this nor John's seems to describe the user-visible way to trigger the symptom. Can we have tests for them? ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-11 21:45 ` Junio C Hamano @ 2014-03-12 23:21 ` brian m. carlson 0 siblings, 0 replies; 21+ messages in thread From: brian m. carlson @ 2014-03-12 23:21 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Jens Lehmann, John Keeping, Guillaume Gelin [-- Attachment #1: Type: text/plain, Size: 586 bytes --] On Tue, Mar 11, 2014 at 02:45:59PM -0700, Junio C Hamano wrote: > Thanks. Neither this nor John's seems to describe the user-visible > way to trigger the symptom. Can we have tests for them? I'll try to get to writing some test today or tomorrow. I just noticed the bugginess by looking at the code, so I'll need to actually spend time reproducing the problem. -- brian m. carlson / brian with sandals: Houston, Texas, US +1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187 [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-08 19:21 ` [PATCH] mv: prevent mismatched data when ignoring errors brian m. carlson 2014-03-11 1:56 ` Jeff King 2014-03-11 21:45 ` Junio C Hamano @ 2014-03-15 16:05 ` Thomas Rast 2014-03-16 2:00 ` Jeff King 2014-03-15 18:56 ` [PATCH v2] " brian m. carlson 3 siblings, 1 reply; 21+ messages in thread From: Thomas Rast @ 2014-03-15 16:05 UTC (permalink / raw) To: brian m. carlson Cc: git, Jens Lehmann, John Keeping, Junio C Hamano, Guillaume Gelin "brian m. carlson" <sandals@crustytoothpaste.net> writes: > We shrink the source and destination arrays, but not the modes or > submodule_gitfile arrays, resulting in potentially mismatched data. Shrink > all the arrays at the same time to prevent this. > > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > --- > builtin/mv.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/builtin/mv.c b/builtin/mv.c > index f99c91e..b20cd95 100644 > --- a/builtin/mv.c > +++ b/builtin/mv.c > @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) > memmove(destination + i, > destination + i + 1, > (argc - i) * sizeof(char *)); > + memmove(modes + i, modes + i + 1, > + (argc - i) * sizeof(char *)); This isn't right -- you are computing the size of things to be moved based on a type of char*, but 'modes' is an enum. (Valgrind spotted this.) -- Thomas Rast tr@thomasrast.ch ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-15 16:05 ` Thomas Rast @ 2014-03-16 2:00 ` Jeff King 2014-03-16 21:20 ` Junio C Hamano 0 siblings, 1 reply; 21+ messages in thread From: Jeff King @ 2014-03-16 2:00 UTC (permalink / raw) To: Thomas Rast Cc: brian m. carlson, git, Jens Lehmann, John Keeping, Junio C Hamano, Guillaume Gelin On Sat, Mar 15, 2014 at 05:05:29PM +0100, Thomas Rast wrote: > > diff --git a/builtin/mv.c b/builtin/mv.c > > index f99c91e..b20cd95 100644 > > --- a/builtin/mv.c > > +++ b/builtin/mv.c > > @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) > > memmove(destination + i, > > destination + i + 1, > > (argc - i) * sizeof(char *)); > > + memmove(modes + i, modes + i + 1, > > + (argc - i) * sizeof(char *)); > > This isn't right -- you are computing the size of things to be moved > based on a type of char*, but 'modes' is an enum. > > (Valgrind spotted this.) Maybe using sizeof(*destination) and sizeof(*modes) would make this less error-prone? -Peff ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-16 2:00 ` Jeff King @ 2014-03-16 21:20 ` Junio C Hamano 2014-03-17 6:33 ` Junio C Hamano 0 siblings, 1 reply; 21+ messages in thread From: Junio C Hamano @ 2014-03-16 21:20 UTC (permalink / raw) To: Jeff King Cc: Thomas Rast, brian m. carlson, git, Jens Lehmann, John Keeping, Guillaume Gelin Jeff King <peff@peff.net> writes: > On Sat, Mar 15, 2014 at 05:05:29PM +0100, Thomas Rast wrote: > >> > diff --git a/builtin/mv.c b/builtin/mv.c >> > index f99c91e..b20cd95 100644 >> > --- a/builtin/mv.c >> > +++ b/builtin/mv.c >> > @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) >> > memmove(destination + i, >> > destination + i + 1, >> > (argc - i) * sizeof(char *)); >> > + memmove(modes + i, modes + i + 1, >> > + (argc - i) * sizeof(char *)); >> >> This isn't right -- you are computing the size of things to be moved >> based on a type of char*, but 'modes' is an enum. >> >> (Valgrind spotted this.) > > Maybe using sizeof(*destination) and sizeof(*modes) would make this less > error-prone? > > -Peff Would it make sense to go one step further to introduce two macros to make this kind of screw-up less likely? 1. "array" is an array that holds "nr" elements. Move "count" elements starting at index "at" down to remove them. #define MOVE_DOWN(array, nr, at, count) The implementation should take advantage of sizeof(*array) to come up with the number of bytes to move. 2. "array" is an array that holds "nr" elements. Move "count" elements starting at index "at" up to make room to copy new elements in. #define MOVE_UP(array, nr, at, count) The implementation should take advantage of sizeof(*array) to come up with the number of bytes to move. Optionally, to make 2. even safer, these macros could take "alloc" to say that "array" has memory allocated to hold "alloc" elements, and the implementation may check "nr + count" does not overflow "alloc". This would make 1. and 2. asymmetric (move-down can do no validation using "alloc", but move-up would be helped), so I am not sure it is a good idea. After letting my eyes coast over hits from "git grep memmove", there do seem to be some places that these would help readability, but not very many. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-16 21:20 ` Junio C Hamano @ 2014-03-17 6:33 ` Junio C Hamano 2014-03-17 15:07 ` Michael Haggerty 0 siblings, 1 reply; 21+ messages in thread From: Junio C Hamano @ 2014-03-17 6:33 UTC (permalink / raw) To: Jeff King Cc: Thomas Rast, brian m. carlson, git, Jens Lehmann, John Keeping, Guillaume Gelin Junio C Hamano <gitster@pobox.com> writes: > Would it make sense to go one step further to introduce two macros > to make this kind of screw-up less likely? > ... > After letting my eyes coast over hits from "git grep memmove", there > do seem to be some places that these would help readability, but not > very many. I see quite a many hits that follow this pattern memmove(array + pos, array + pos + 1, sizeof(*array) * (nr - pos)) to make a single slot in a middle of array available, which would be good candidates to use MOVE_DOWN(). Just to show a few: builtin/mv.c:226: memmove(source + i, source + i + 1, builtin/mv.c-227- (argc - i) * sizeof(char *)); builtin/mv.c:228: memmove(destination + i, builtin/mv.c-229- destination + i + 1, builtin/mv.c-230- (argc - i) * sizeof(char *)); cache-tree.c:92: memmove(it->down + pos + 1, cache-tree.c-93- it->down + pos, cache-tree.c-94- sizeof(down) * (it->subtree_nr - pos - 1)); Perhaps something like this patch to start off; I am not sure MOVE_DOWN_BOUNDED is needed, though. cache.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/cache.h b/cache.h index b66cb49..b2615ab 100644 --- a/cache.h +++ b/cache.h @@ -455,6 +455,39 @@ extern int daemonize(void); } \ } while (0) +/* + * With an array "array" that currently holds "nr" elements, move + * elements at "at" and later down by "count" elements to make room to + * add in new elements. The caller is responsible for making sure + * that the array has enough room to hold "nr" + "count" slots. + */ +#define MOVE_DOWN(array, nr, at, count) \ + memmove((array) + (at) + (count), \ + (array) + (at), \ + sizeof((array)[0]) * ((nr) - (at))) + +/* + * With an array "array" that has enough memory to hold "alloc" + * elements allocated and currently holds "nr" elements, move elements + * at "at" and later down by "count" elements to make room to add in + * new elements. + */ +#define MOVE_DOWN_BOUNDED(array, nr, at, count, alloc) \ + do { \ + if ((alloc) <= (nr) + (count)) \ + BUG("MOVE_DOWN beyond the end of an array"); \ + MOVE_DOWN((array), (nr), (at), (count)); \ + } while (0) + +/* + * With an array "array" that curently holds "nr" elements, move elements + * at "at" + "count" and later down by "count" elements, removing the + * elements between "at" and "at" + "count". + */ +#define MOVE_UP(array, nr, at, count) \ + memmove((array) + (at), (array) + (at) + (count), \ + sizeof((array)[0]) * ((nr) - ((at) + (count)))) + /* Initialize and use the cache information */ extern int read_index(struct index_state *); extern int read_index_preload(struct index_state *, const struct pathspec *pathspec); ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-17 6:33 ` Junio C Hamano @ 2014-03-17 15:07 ` Michael Haggerty 2014-03-17 19:06 ` Eric Sunshine 2014-03-18 22:31 ` Junio C Hamano 0 siblings, 2 replies; 21+ messages in thread From: Michael Haggerty @ 2014-03-17 15:07 UTC (permalink / raw) To: Junio C Hamano Cc: Jeff King, Thomas Rast, brian m. carlson, git, Jens Lehmann, John Keeping, Guillaume Gelin On 03/17/2014 07:33 AM, Junio C Hamano wrote: > Junio C Hamano <gitster@pobox.com> writes: > >> Would it make sense to go one step further to introduce two macros >> to make this kind of screw-up less likely? >> ... >> After letting my eyes coast over hits from "git grep memmove", there >> do seem to be some places that these would help readability, but not >> very many. > > I see quite a many hits that follow this pattern > > memmove(array + pos, array + pos + 1, sizeof(*array) * (nr - pos)) > > to make a single slot in a middle of array available, which would be > good candidates to use MOVE_DOWN(). Just to show a few: > > builtin/mv.c:226: memmove(source + i, source + i + 1, > builtin/mv.c-227- (argc - i) * sizeof(char *)); > builtin/mv.c:228: memmove(destination + i, > builtin/mv.c-229- destination + i + 1, > builtin/mv.c-230- (argc - i) * sizeof(char *)); > cache-tree.c:92: memmove(it->down + pos + 1, > cache-tree.c-93- it->down + pos, > cache-tree.c-94- sizeof(down) * (it->subtree_nr - pos - 1)); > > > Perhaps something like this patch to start off; I am not sure > MOVE_DOWN_BOUNDED is needed, though. > > cache.h | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/cache.h b/cache.h > index b66cb49..b2615ab 100644 > --- a/cache.h > +++ b/cache.h > @@ -455,6 +455,39 @@ extern int daemonize(void); > } \ > } while (0) > > +/* > + * With an array "array" that currently holds "nr" elements, move > + * elements at "at" and later down by "count" elements to make room to > + * add in new elements. The caller is responsible for making sure > + * that the array has enough room to hold "nr" + "count" slots. > + */ > +#define MOVE_DOWN(array, nr, at, count) \ > + memmove((array) + (at) + (count), \ > + (array) + (at), \ > + sizeof((array)[0]) * ((nr) - (at))) > + > +/* > + * With an array "array" that has enough memory to hold "alloc" > + * elements allocated and currently holds "nr" elements, move elements > + * at "at" and later down by "count" elements to make room to add in > + * new elements. > + */ > +#define MOVE_DOWN_BOUNDED(array, nr, at, count, alloc) \ > + do { \ > + if ((alloc) <= (nr) + (count)) \ > + BUG("MOVE_DOWN beyond the end of an array"); \ > + MOVE_DOWN((array), (nr), (at), (count)); \ > + } while (0) > + > +/* > + * With an array "array" that curently holds "nr" elements, move elements > + * at "at" + "count" and later down by "count" elements, removing the > + * elements between "at" and "at" + "count". > + */ > +#define MOVE_UP(array, nr, at, count) \ > + memmove((array) + (at), (array) + (at) + (count), \ > + sizeof((array)[0]) * ((nr) - ((at) + (count)))) > + > /* Initialize and use the cache information */ > extern int read_index(struct index_state *); > extern int read_index_preload(struct index_state *, const struct pathspec *pathspec); I had recently been thinking along the same lines. In many of the potential callers that I noticed, ALLOC_GROW() was used immediately before making space in the array for a new element. So I suggest something more like +#define MOVE_DOWN(array, nr, at, count) \ + memmove((array) + (at) + (count), \ + (array) + (at), \ + sizeof((array)[0]) * ((nr) - (at))) +#define ALLOC_INSERT_GAP(array, nr, at, count, alloc) \ + do { \ + ALLOC_GROW((array), (nr) + (count), (alloc)); \ + MOVE_DOWN((array), (nr), (at), (count)); \ + } while (0) Also, count==1 is so frequent that this special case might deserve its own macro pair. I'm not inspired by these macro names, though. Michael -- Michael Haggerty mhagger@alum.mit.edu http://softwareswirl.blogspot.com/ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-17 15:07 ` Michael Haggerty @ 2014-03-17 19:06 ` Eric Sunshine 2014-03-17 22:04 ` Jeff King 2014-03-18 22:31 ` Junio C Hamano 1 sibling, 1 reply; 21+ messages in thread From: Eric Sunshine @ 2014-03-17 19:06 UTC (permalink / raw) To: Michael Haggerty Cc: Junio C Hamano, Jeff King, Thomas Rast, brian m. carlson, Git List, Jens Lehmann, John Keeping, Guillaume Gelin On Mon, Mar 17, 2014 at 11:07 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote: > On 03/17/2014 07:33 AM, Junio C Hamano wrote: >> Junio C Hamano <gitster@pobox.com> writes: >> >>> Would it make sense to go one step further to introduce two macros >>> to make this kind of screw-up less likely? > potential callers that I noticed, ALLOC_GROW() was used immediately > before making space in the array for a new element. So I suggest > something more like > > +#define MOVE_DOWN(array, nr, at, count) \ > + memmove((array) + (at) + (count), \ > + (array) + (at), \ > + sizeof((array)[0]) * ((nr) - (at))) Each time I read these, my brain (for whatever reason) interprets the names UP and DOWN opposite of the intended meaning, which makes them confusing. Perhaps INSERT_GAP and CLOSE_GAP would avoid such problems, and be more consistent with Michael's proposed ALLOC_INSERT_GAP. > +#define ALLOC_INSERT_GAP(array, nr, at, count, alloc) \ > + do { \ > + ALLOC_GROW((array), (nr) + (count), (alloc)); \ > + MOVE_DOWN((array), (nr), (at), (count)); \ > + } while (0) > > Also, count==1 is so frequent that this special case might deserve its > own macro pair. > > I'm not inspired by these macro names, though. > > Michael > > -- > Michael Haggerty > mhagger@alum.mit.edu > http://softwareswirl.blogspot.com/ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-17 19:06 ` Eric Sunshine @ 2014-03-17 22:04 ` Jeff King 0 siblings, 0 replies; 21+ messages in thread From: Jeff King @ 2014-03-17 22:04 UTC (permalink / raw) To: Eric Sunshine Cc: Michael Haggerty, Junio C Hamano, Thomas Rast, brian m. carlson, Git List, Jens Lehmann, John Keeping, Guillaume Gelin On Mon, Mar 17, 2014 at 03:06:02PM -0400, Eric Sunshine wrote: > On Mon, Mar 17, 2014 at 11:07 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote: > > On 03/17/2014 07:33 AM, Junio C Hamano wrote: > >> Junio C Hamano <gitster@pobox.com> writes: > >> > >>> Would it make sense to go one step further to introduce two macros > >>> to make this kind of screw-up less likely? > > potential callers that I noticed, ALLOC_GROW() was used immediately > > before making space in the array for a new element. So I suggest > > something more like > > > > +#define MOVE_DOWN(array, nr, at, count) \ > > + memmove((array) + (at) + (count), \ > > + (array) + (at), \ > > + sizeof((array)[0]) * ((nr) - (at))) > > Each time I read these, my brain (for whatever reason) interprets the > names UP and DOWN opposite of the intended meaning, which makes them > confusing. Perhaps INSERT_GAP and CLOSE_GAP would avoid such problems, > and be more consistent with Michael's proposed ALLOC_INSERT_GAP. Yeah, the UP/DOWN are very confusing to me. Something like SHRINK/EXPAND (with the latter handling the ALLOC_GROW for us) makes more sense to me. Those terms do not explicitly specify that we are doing it in the middle (whereas GAP does), but I think it is fairly obvious from the parameters what each is used for. Side note: I had _almost_ added something to my original email suggesting more use of macros to embody common idioms. For example, in the vast majority of malloc cases, you could using something like: #define ALLOC_OBJS(x,n) do { x = xmalloc(sizeof(*x) * (n)); } while(0) #define ALLOC_OBJ(x) ALLOC_OBJS(x,1) That eliminates a whole possible class of errors. But it's also un-idiomatic as hell, and the resulting confusion can cause its own problems. So I refrained from suggesting it. I think as long as a macro is expressing a more high-level intent, though, paying that cost can be worth it. By itself, wrapping memmove to use sizeof(*array) does not seem all that exciting. But wrapping a few specific cases like shrink/expand probably does make the code more readable. -Peff ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] mv: prevent mismatched data when ignoring errors. 2014-03-17 15:07 ` Michael Haggerty 2014-03-17 19:06 ` Eric Sunshine @ 2014-03-18 22:31 ` Junio C Hamano 1 sibling, 0 replies; 21+ messages in thread From: Junio C Hamano @ 2014-03-18 22:31 UTC (permalink / raw) To: Michael Haggerty Cc: Jeff King, Thomas Rast, brian m. carlson, git, Jens Lehmann, John Keeping, Guillaume Gelin Michael Haggerty <mhagger@alum.mit.edu> writes: > I had recently been thinking along the same lines. In many of the > potential callers that I noticed, ALLOC_GROW() was used immediately > before making space in the array for a new element. So I suggest > something more like > > +#define MOVE_DOWN(array, nr, at, count) \ > + memmove((array) + (at) + (count), \ > + (array) + (at), \ > + sizeof((array)[0]) * ((nr) - (at))) > +#define ALLOC_INSERT_GAP(array, nr, at, count, alloc) \ > + do { \ > + ALLOC_GROW((array), (nr) + (count), (alloc)); \ > + MOVE_DOWN((array), (nr), (at), (count)); \ > + } while (0) > > Also, count==1 is so frequent that this special case might deserve its > own macro pair. Yeah, probably. > I'm not inspired by these macro names, though. Me neither, about ups and downs. Peff's suggestion to name these around the concept of "gap" sounded sensible. ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2] mv: prevent mismatched data when ignoring errors. 2014-03-08 19:21 ` [PATCH] mv: prevent mismatched data when ignoring errors brian m. carlson ` (2 preceding siblings ...) 2014-03-15 16:05 ` Thomas Rast @ 2014-03-15 18:56 ` brian m. carlson 2014-03-16 2:00 ` Jeff King 3 siblings, 1 reply; 21+ messages in thread From: brian m. carlson @ 2014-03-15 18:56 UTC (permalink / raw) To: git; +Cc: Jens Lehmann, John Keeping, Junio C Hamano, Guillaume Gelin We shrink the source and destination arrays, but not the modes or submodule_gitfile arrays, resulting in potentially mismatched data. Shrink all the arrays at the same time to prevent this. Add tests to ensure the problem does not recur. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> --- I attempted to come up with a second patch that would refactor out the four different arrays into one array of struct, as Jeff suggested, but it became very ugly very quickly. So this patch simply fixes the problem and adds tests. builtin/mv.c | 5 +++++ t/t7001-mv.sh | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/builtin/mv.c b/builtin/mv.c index f99c91e..09bbc63 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -230,6 +230,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix) memmove(destination + i, destination + i + 1, (argc - i) * sizeof(char *)); + memmove(modes + i, modes + i + 1, + (argc - i) * sizeof(enum update_mode)); + memmove(submodule_gitfile + i, + submodule_gitfile + i + 1, + (argc - i) * sizeof(char *)); i--; } } else diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index e3c8c2c..215d43d 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -294,7 +294,8 @@ test_expect_success 'setup submodule' ' git submodule add ./. sub && echo content >file && git add file && - git commit -m "added sub and file" + git commit -m "added sub and file" && + git branch submodule ' test_expect_success 'git mv cannot move a submodule in a file' ' @@ -463,4 +464,14 @@ test_expect_success 'checking out a commit before submodule moved needs manual u ! test -s actual ' +test_expect_success 'mv -k does not accidentally destroy submodules' ' + git checkout submodule && + mkdir dummy dest && + git mv -k dummy sub dest && + git status --porcelain >actual && + grep "^R sub -> dest/sub" actual && + git reset --hard && + git checkout . +' + test_done -- 1.9.0.1010.g6633b85.dirty ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v2] mv: prevent mismatched data when ignoring errors. 2014-03-15 18:56 ` [PATCH v2] " brian m. carlson @ 2014-03-16 2:00 ` Jeff King 0 siblings, 0 replies; 21+ messages in thread From: Jeff King @ 2014-03-16 2:00 UTC (permalink / raw) To: brian m. carlson Cc: git, Jens Lehmann, John Keeping, Junio C Hamano, Guillaume Gelin On Sat, Mar 15, 2014 at 06:56:52PM +0000, brian m. carlson wrote: > We shrink the source and destination arrays, but not the modes or > submodule_gitfile arrays, resulting in potentially mismatched data. Shrink > all the arrays at the same time to prevent this. Add tests to ensure the > problem does not recur. > > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> > --- > > I attempted to come up with a second patch that would refactor out the > four different arrays into one array of struct, as Jeff suggested, but > it became very ugly very quickly. So this patch simply fixes the > problem and adds tests. >From my brief look, I feared that might be the case. Oh well, thanks for trying. -Peff ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2014-03-18 22:31 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-03-08 16:23 git 1.9.0 segfault Guillaume Gelin 2014-03-08 16:46 ` brian m. carlson 2014-03-08 18:12 ` John Keeping 2014-03-08 18:35 ` [PATCH] builtin/mv: fix out of bounds write John Keeping 2014-03-08 19:15 ` brian m. carlson 2014-03-08 19:29 ` [PATCH v2] " John Keeping 2014-03-08 19:21 ` [PATCH] mv: prevent mismatched data when ignoring errors brian m. carlson 2014-03-11 1:56 ` Jeff King 2014-03-11 2:00 ` brian m. carlson 2014-03-11 21:45 ` Junio C Hamano 2014-03-12 23:21 ` brian m. carlson 2014-03-15 16:05 ` Thomas Rast 2014-03-16 2:00 ` Jeff King 2014-03-16 21:20 ` Junio C Hamano 2014-03-17 6:33 ` Junio C Hamano 2014-03-17 15:07 ` Michael Haggerty 2014-03-17 19:06 ` Eric Sunshine 2014-03-17 22:04 ` Jeff King 2014-03-18 22:31 ` Junio C Hamano 2014-03-15 18:56 ` [PATCH v2] " brian m. carlson 2014-03-16 2:00 ` Jeff King
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).