* [patch] git: fix memory leak in checkout-cache.c
@ 2005-04-14 11:26 Ingo Molnar
2005-04-14 11:35 ` [patch] git: fix memory leak #2 " Ingo Molnar
2005-04-14 12:08 ` [patch] git: fix memory leak in show-diff.c Ingo Molnar
0 siblings, 2 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 11:26 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a memory leak in checkout-cache.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- checkout-cache.c.orig
+++ checkout-cache.c
@@ -48,6 +48,7 @@ static void create_directories(const cha
buf[len] = 0;
mkdir(buf, 0755);
}
+ free(buf);
}
static int create_file(const char *path, unsigned int mode)
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leak #2 in checkout-cache.c
2005-04-14 11:26 [patch] git: fix memory leak in checkout-cache.c Ingo Molnar
@ 2005-04-14 11:35 ` Ingo Molnar
2005-04-14 11:43 ` [patch] git: cleanup in ls-tree.c Ingo Molnar
` (2 more replies)
2005-04-14 12:08 ` [patch] git: fix memory leak in show-diff.c Ingo Molnar
1 sibling, 3 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 11:35 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes another (very rare) memory leak in checkout-cache.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- checkout-cache.c.orig
+++ checkout-cache.c
@@ -74,6 +74,8 @@ static int write_entry(struct cache_entr
new = read_sha1_file(ce->sha1, type, &size);
if (!new || strcmp(type, "blob")) {
+ if (new)
+ free(new);
return error("checkout-cache: unable to read sha1 file of %s (%s)",
ce->name, sha1_to_hex(ce->sha1));
}
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: cleanup in ls-tree.c
2005-04-14 11:35 ` [patch] git: fix memory leak #2 " Ingo Molnar
@ 2005-04-14 11:43 ` Ingo Molnar
2005-04-14 11:54 ` [patch] git: fix memory leaks in read-tree.c Ingo Molnar
2005-04-14 11:58 ` [patch] git: fix rare memory leak in rev-tree.c Ingo Molnar
2 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 11:43 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
cleanup: this patch adds a free() to ls-tree.c.
(Technically it's not a memory leak yet because the buffer is allocated
once by the function and then the utility exits - but it's a tad cleaner
to not leave such assumptions in the code, so that if someone reuses the
function (or extends the utility to include a loop) the uncleanliness
doesnt develop into a real memory leak.)
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- ls-tree.c.orig
+++ ls-tree.c
@@ -33,6 +33,8 @@ static int list(unsigned char *sha1)
type = S_ISDIR(mode) ? "tree" : "blob";
printf("%03o\t%s\t%s\t%s\n", mode, type, sha1_to_hex(sha1), path);
}
+ free(buffer);
+
return 0;
}
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leaks in read-tree.c
2005-04-14 11:35 ` [patch] git: fix memory leak #2 " Ingo Molnar
2005-04-14 11:43 ` [patch] git: cleanup in ls-tree.c Ingo Molnar
@ 2005-04-14 11:54 ` Ingo Molnar
2005-04-14 11:58 ` [patch] git: fix rare memory leak in rev-tree.c Ingo Molnar
2 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 11:54 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes one common, and 4 rare memory leaks in read-tree.c.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- read-tree.c.orig
+++ read-tree.c
@@ -23,23 +23,27 @@ static int read_one_entry(unsigned char
static int read_tree(unsigned char *sha1, const char *base, int baselen)
{
- void *buffer;
+ void *buffer0, *buffer;
unsigned long size;
char type[20];
- buffer = read_sha1_file(sha1, type, &size);
+ buffer0 = buffer = read_sha1_file(sha1, type, &size);
if (!buffer)
return -1;
- if (strcmp(type, "tree"))
+ if (strcmp(type, "tree")) {
+ free(buffer);
return -1;
+ }
while (size) {
int len = strlen(buffer)+1;
unsigned char *sha1 = buffer + len;
char *path = strchr(buffer, ' ')+1;
unsigned int mode;
- if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1)
+ if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1) {
+ free(buffer0);
return -1;
+ }
buffer = sha1 + 20;
size -= len + 20;
@@ -53,13 +57,19 @@ static int read_tree(unsigned char *sha1
newbase[baselen + pathlen] = '/';
retval = read_tree(sha1, newbase, baselen + pathlen + 1);
free(newbase);
- if (retval)
+ if (retval) {
+ free(buffer0);
return -1;
+ }
continue;
}
- if (read_one_entry(sha1, base, baselen, path, mode) < 0)
+ if (read_one_entry(sha1, base, baselen, path, mode) < 0) {
+ free(buffer0);
return -1;
+ }
}
+ free(buffer0);
+
return 0;
}
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix rare memory leak in rev-tree.c
2005-04-14 11:35 ` [patch] git: fix memory leak #2 " Ingo Molnar
2005-04-14 11:43 ` [patch] git: cleanup in ls-tree.c Ingo Molnar
2005-04-14 11:54 ` [patch] git: fix memory leaks in read-tree.c Ingo Molnar
@ 2005-04-14 11:58 ` Ingo Molnar
2005-04-14 12:05 ` [patch] git: report parse_commit() errors " Ingo Molnar
2 siblings, 1 reply; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 11:58 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a rare memory leak in rev-tree.c.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- rev-tree.c.orig
+++ rev-tree.c
@@ -73,8 +73,11 @@ static int parse_commit(unsigned char *s
rev->flags |= SEEN;
buffer = bufptr = read_sha1_file(sha1, type, &size);
- if (!buffer || strcmp(type, "commit"))
+ if (!buffer || strcmp(type, "commit")) {
+ if (buffer)
+ free(buffer);
return -1;
+ }
bufptr += 46; /* "tree " + "hex sha1" + "\n" */
while (!memcmp(bufptr, "parent ", 7) && !get_sha1_hex(bufptr+7, parent)) {
add_relationship(rev, parent);
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: report parse_commit() errors in rev-tree.c
2005-04-14 11:58 ` [patch] git: fix rare memory leak in rev-tree.c Ingo Molnar
@ 2005-04-14 12:05 ` Ingo Molnar
0 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 12:05 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
make actual use of the parse_commit() return value and print a warning,
instead of silently ignoring it. Should never trigger on a valid DB.
(alternatively we might use a die() in the sanity check place and could
remove all the return code handling?)
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- rev-tree.c.orig
+++ rev-tree.c
@@ -64,6 +64,7 @@ static unsigned long parse_commit_date(c
static int parse_commit(unsigned char *sha1)
{
struct revision *rev = lookup_rev(sha1);
+ int ret = 0;
if (!(rev->flags & SEEN)) {
void *buffer, *bufptr;
@@ -81,13 +82,13 @@ static int parse_commit(unsigned char *s
bufptr += 46; /* "tree " + "hex sha1" + "\n" */
while (!memcmp(bufptr, "parent ", 7) && !get_sha1_hex(bufptr+7, parent)) {
add_relationship(rev, parent);
- parse_commit(parent);
+ ret |= parse_commit(parent);
bufptr += 48; /* "parent " + "hex sha1" + "\n" */
}
rev->date = parse_commit_date(bufptr);
free(buffer);
}
- return 0;
+ return ret;
}
static void read_cache_file(const char *path)
@@ -208,7 +209,8 @@ int main(int argc, char **argv)
}
if (nr >= MAX_COMMITS || get_sha1_hex(arg, sha1[nr]))
usage("rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id>]");
- parse_commit(sha1[nr]);
+ if (parse_commit(sha1[nr]))
+ fprintf(stderr, "warning: rev-tree: bad commit!\n");
nr++;
}
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leak in show-diff.c
2005-04-14 11:26 [patch] git: fix memory leak in checkout-cache.c Ingo Molnar
2005-04-14 11:35 ` [patch] git: fix memory leak #2 " Ingo Molnar
@ 2005-04-14 12:08 ` Ingo Molnar
2005-04-14 12:18 ` [patch] git: fix overflow in update-cache.c Ingo Molnar
` (2 more replies)
1 sibling, 3 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 12:08 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a memory leak in show-diff.c.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- show-diff.c.orig
+++ show-diff.c
@@ -53,6 +53,7 @@ static void show_diff_empty(struct cache
printf("\n");
fflush(stdout);
}
+ free(old);
}
int main(int argc, char **argv)
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix overflow in update-cache.c
2005-04-14 12:08 ` [patch] git: fix memory leak in show-diff.c Ingo Molnar
@ 2005-04-14 12:18 ` Ingo Molnar
2005-04-14 12:23 ` [patch] cleanup: read_sha1_file() -> malloc_read_sha1_file() Ingo Molnar
` (2 more replies)
2005-04-14 12:32 ` [patch] git: fix memory leaks in read-cache.c Ingo Molnar
2005-04-14 13:12 ` [patch] git: fix memory leak in write-tree.c Ingo Molnar
2 siblings, 3 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 12:18 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a 1-byte overflow in update-cache.c (probably not
exploitable). A specially crafted db object might trigger this overflow.
the bug is that normally the 'type' field is parsed by read_sha1_file(),
via:
if (sscanf(buffer, "%10s %lu", type, size) != 2)
i.e. 0-10 long strings, which take 1-11 bytes of space. Normally the
type strings are stored in char [20] arrays, but in update-cache.c that
is char [10], so a 1 byte overflow might occur.
This should not happen with a 'friendly' DB, as the longest type string
("commit") is 7 bytes long. The fix is to use the customary char [20].
(someone might want to clean those open-coded constants up with a
TYPE_LEN define, they do tend to cause problems like this. I'm not
against open-coded constants (they make code much more readable), but
for fields that get filled in from possibly hostile objects this is
playing with fire.)
hey, this might be the first true security fix for GIT? ;-)
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- update-cache.c.orig
+++ update-cache.c
@@ -139,7 +139,7 @@ static int compare_data(struct cache_ent
if (fd >= 0) {
void *buffer;
unsigned long size;
- char type[10];
+ char type[20];
buffer = read_sha1_file(ce->sha1, type, &size);
if (buffer) {
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] cleanup: read_sha1_file() -> malloc_read_sha1_file()
2005-04-14 12:18 ` [patch] git: fix overflow in update-cache.c Ingo Molnar
@ 2005-04-14 12:23 ` Ingo Molnar
2005-04-14 12:53 ` [patch] git: fix 1-byte overflow in show-files.c Ingo Molnar
2005-04-14 13:03 ` [patch] git: fix memory leaks in update-cache.c Ingo Molnar
2 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 12:23 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch renames read_sha1_file() to malloc_read_sha1_file().
There were a handful of memory-leaks related to read_sha1_file(), and
some of those could possibly have been found sooner if the name
indicated that an implicit malloc() is occurs within read_sha1_file().
This patch is ontop of the previous patches i sent.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- cat-file.c.orig
+++ cat-file.c
@@ -14,7 +14,7 @@ int main(int argc, char **argv)
if (argc != 3 || get_sha1_hex(argv[2], sha1))
usage("cat-file [-t | tagname] <sha1>");
- buf = read_sha1_file(sha1, type, &size);
+ buf = malloc_read_sha1_file(sha1, type, &size);
if (!buf)
die("cat-file %s: bad file", argv[2]);
if (!strcmp("-t", argv[1])) {
--- merge-tree.c.orig
+++ merge-tree.c
@@ -11,7 +11,7 @@ static struct tree_entry *read_tree(unsi
{
char type[20];
unsigned long size;
- void *buf = read_sha1_file(sha1, type, &size);
+ void *buf = malloc_read_sha1_file(sha1, type, &size);
struct tree_entry *ret = NULL, **tp = &ret;
if (!buf || strcmp(type, "tree"))
--- diff-tree.c.orig
+++ diff-tree.c
@@ -62,7 +62,7 @@ static void show_file(const char *prefix
char *newbase = malloc_base(base, path, strlen(path));
void *tree;
- tree = read_sha1_file(sha1, type, &size);
+ tree = malloc_read_sha1_file(sha1, type, &size);
if (!tree || strcmp(type, "tree"))
die("corrupt tree sha %s", sha1_to_hex(sha1));
@@ -164,10 +164,10 @@ static int diff_tree_sha1(const unsigned
char type[20];
int retval;
- tree1 = read_sha1_file(old, type, &size1);
+ tree1 = malloc_read_sha1_file(old, type, &size1);
if (!tree1 || strcmp(type, "tree"))
die("unable to read source tree (%s)", sha1_to_hex(old));
- tree2 = read_sha1_file(new, type, &size2);
+ tree2 = malloc_read_sha1_file(new, type, &size2);
if (!tree2 || strcmp(type, "tree"))
die("unable to read destination tree (%s)", sha1_to_hex(new));
retval = diff_tree(tree1, size1, tree2, size2, base);
--- show-diff.c.orig
+++ show-diff.c
@@ -25,7 +25,7 @@ static void show_diff_empty(struct cache
int lines=0;
unsigned char type[20], *p, *end;
- old = read_sha1_file(ce->sha1, type, &size);
+ old = malloc_read_sha1_file(ce->sha1, type, &size);
if (size > 0) {
int startline = 1;
int c = 0;
@@ -99,7 +99,7 @@ int main(int argc, char **argv)
if (silent)
continue;
- new = read_sha1_file(ce->sha1, type, &size);
+ new = malloc_read_sha1_file(ce->sha1, type, &size);
show_differences(ce->name, new, size);
free(new);
}
--- read-cache.c.orig
+++ read-cache.c
@@ -183,7 +183,7 @@ void * unpack_sha1_file(void *map, unsig
return buf;
}
-void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
+void * malloc_read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
{
unsigned long mapsize;
void *map, *buf;
--- update-cache.c.orig
+++ update-cache.c
@@ -141,7 +141,7 @@ static int compare_data(struct cache_ent
unsigned long size;
char type[20];
- buffer = read_sha1_file(ce->sha1, type, &size);
+ buffer = malloc_read_sha1_file(ce->sha1, type, &size);
if (buffer) {
if (size == expected_size && !strcmp(type, "blob"))
match = match_data(fd, buffer, size);
--- ls-tree.c.orig
+++ ls-tree.c
@@ -11,7 +11,7 @@ static int list(unsigned char *sha1)
unsigned long size;
char type[20];
- buffer = read_sha1_file(sha1, type, &size);
+ buffer = malloc_read_sha1_file(sha1, type, &size);
if (!buffer)
die("unable to read sha1 file");
if (strcmp(type, "tree"))
--- checkout-cache.c.orig
+++ checkout-cache.c
@@ -72,7 +72,7 @@ static int write_entry(struct cache_entr
long wrote;
char type[20];
- new = read_sha1_file(ce->sha1, type, &size);
+ new = malloc_read_sha1_file(ce->sha1, type, &size);
if (!new || strcmp(type, "blob")) {
if (new)
free(new);
--- cache.h.orig
+++ cache.h
@@ -95,7 +95,7 @@ extern int write_sha1_buffer(const unsig
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
extern void * map_sha1_file(const unsigned char *sha1, unsigned long *size);
extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);
-extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
+extern void * malloc_read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
extern int write_sha1_file(char *buf, unsigned len, unsigned char *return_sha1);
extern int check_sha1_signature(unsigned char *sha1, void *buf, unsigned long size);
--- rev-tree.c.orig
+++ rev-tree.c
@@ -73,7 +73,7 @@ static int parse_commit(unsigned char *s
unsigned char parent[20];
rev->flags |= SEEN;
- buffer = bufptr = read_sha1_file(sha1, type, &size);
+ buffer = bufptr = malloc_read_sha1_file(sha1, type, &size);
if (!buffer || strcmp(type, "commit")) {
if (buffer)
free(buffer);
--- read-tree.c.orig
+++ read-tree.c
@@ -27,7 +27,7 @@ static int read_tree(unsigned char *sha1
unsigned long size;
char type[20];
- buffer0 = buffer = read_sha1_file(sha1, type, &size);
+ buffer0 = buffer = malloc_read_sha1_file(sha1, type, &size);
if (!buffer)
return -1;
if (strcmp(type, "tree")) {
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leaks in read-cache.c
2005-04-14 12:08 ` [patch] git: fix memory leak in show-diff.c Ingo Molnar
2005-04-14 12:18 ` [patch] git: fix overflow in update-cache.c Ingo Molnar
@ 2005-04-14 12:32 ` Ingo Molnar
2005-04-14 12:39 ` [patch] git: fix memory leak #2 " Ingo Molnar
2005-04-14 13:12 ` [patch] git: fix memory leak in write-tree.c Ingo Molnar
2 siblings, 1 reply; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 12:32 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a common and a rare memory leak in read-cache.c.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- read-cache.c.orig
+++ read-cache.c
@@ -226,8 +226,11 @@ int write_sha1_file(char *buf, unsigned
SHA1_Update(&c, compressed, size);
SHA1_Final(sha1, &c);
- if (write_sha1_buffer(sha1, compressed, size) < 0)
+ if (write_sha1_buffer(sha1, compressed, size) < 0) {
+ free(compressed);
return -1;
+ }
+ free(compressed);
if (returnsha1)
memcpy(returnsha1, sha1, 20);
return 0;
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leak #2 in read-cache.c
2005-04-14 12:32 ` [patch] git: fix memory leaks in read-cache.c Ingo Molnar
@ 2005-04-14 12:39 ` Ingo Molnar
2005-04-14 13:25 ` Ingo Molnar
2005-04-14 15:11 ` Linus Torvalds
0 siblings, 2 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 12:39 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a memory leak in read-cache.c: when there's cache entry
collision we should free the previous one.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- read-cache.c.orig
+++ read-cache.c
@@ -369,6 +369,7 @@ int add_cache_entry(struct cache_entry *
/* existing match? Just replace it */
if (pos >= 0) {
+ free(active_cache[pos]);
active_cache[pos] = ce;
return 0;
}
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix 1-byte overflow in show-files.c
2005-04-14 12:18 ` [patch] git: fix overflow in update-cache.c Ingo Molnar
2005-04-14 12:23 ` [patch] cleanup: read_sha1_file() -> malloc_read_sha1_file() Ingo Molnar
@ 2005-04-14 12:53 ` Ingo Molnar
2005-04-17 23:59 ` Petr Baudis
2005-04-14 13:03 ` [patch] git: fix memory leaks in update-cache.c Ingo Molnar
2 siblings, 1 reply; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 12:53 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a 1-byte overflow in show-files.c (looks narrow is is
probably not exploitable). A specially crafted db object (tree) might
trigger this overflow.
'fullname' is an array of 4096+1 bytes, and we do readdir(), which
produces entries that have strings with a length of 0-255 bytes. With a
long enough 'base', it's possible to construct a tree with a name in it
that has directory whose name ends precisely at offset 4095. At that
point this code:
case DT_DIR:
memcpy(fullname + baselen + len, "/", 2);
will attempt to append a "/" string to the directory name - resulting in
a 1-byte overflow (a zero byte is written to offset 4097, which is
outside the array).
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- show-files.c.orig
+++ show-files.c
@@ -49,7 +49,7 @@ static void read_directory(const char *p
if (dir) {
struct dirent *de;
- char fullname[MAXPATHLEN + 1];
+ char fullname[MAXPATHLEN + 2]; // +1 byte for trailing slash
memcpy(fullname, base, baselen);
while ((de = readdir(dir)) != NULL) {
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leaks in update-cache.c
2005-04-14 12:18 ` [patch] git: fix overflow in update-cache.c Ingo Molnar
2005-04-14 12:23 ` [patch] cleanup: read_sha1_file() -> malloc_read_sha1_file() Ingo Molnar
2005-04-14 12:53 ` [patch] git: fix 1-byte overflow in show-files.c Ingo Molnar
@ 2005-04-14 13:03 ` Ingo Molnar
2005-04-14 13:08 ` [patch] git: clean up add_file_to_cache() " Ingo Molnar
2005-04-14 13:31 ` [patch] git: fix memory leak #3 " Ingo Molnar
2 siblings, 2 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 13:03 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes two memory leaks in update-cache.c: we didnt free the
temporary input and output buffers used for compression.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- update-cache.c.orig
+++ update-cache.c
@@ -23,13 +23,17 @@ static int index_fd(const char *path, in
void *metadata = malloc(namelen + 200);
void *in;
SHA_CTX c;
+ int ret;
in = "";
if (size)
in = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- if (!out || (int)(long)in == -1)
+ if (!out || (int)(long)in == -1) {
+ free(out);
+ free(metadata);
return -1;
+ }
memset(&stream, 0, sizeof(stream));
deflateInit(&stream, Z_BEST_COMPRESSION);
@@ -58,7 +62,12 @@ static int index_fd(const char *path, in
SHA1_Update(&c, out, stream.total_out);
SHA1_Final(ce->sha1, &c);
- return write_sha1_buffer(ce->sha1, out, stream.total_out);
+ ret = write_sha1_buffer(ce->sha1, out, stream.total_out);
+
+ free(out);
+ free(metadata);
+
+ return ret;
}
/*
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: clean up add_file_to_cache() in update-cache.c
2005-04-14 13:03 ` [patch] git: fix memory leaks in update-cache.c Ingo Molnar
@ 2005-04-14 13:08 ` Ingo Molnar
2005-04-14 13:31 ` [patch] git: fix memory leak #3 " Ingo Molnar
1 sibling, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 13:08 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch cleans up add_file_to_cache() to free up all memory it
allocates. This has no significance right now as the only user of
add_file_to_cache() die()s immediately in the 'leak' paths - but if the
function is ever used without dying then this uncleanliness could lead
to a memory leak.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- update-cache.c.orig
+++ update-cache.c
@@ -120,10 +120,17 @@ static int add_file_to_cache(char *path)
ce->st_size = st.st_size;
ce->namelen = namelen;
- if (index_fd(path, namelen, ce, fd, &st) < 0)
+ if (index_fd(path, namelen, ce, fd, &st) < 0) {
+ free(ce);
return -1;
+ }
- return add_cache_entry(ce, allow_add);
+ if (add_cache_entry(ce, allow_add)) {
+ free(ce);
+ return -1;
+ }
+
+ return 0;
}
static int match_data(int fd, void *buffer, unsigned long size)
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leak in write-tree.c
2005-04-14 12:08 ` [patch] git: fix memory leak in show-diff.c Ingo Molnar
2005-04-14 12:18 ` [patch] git: fix overflow in update-cache.c Ingo Molnar
2005-04-14 12:32 ` [patch] git: fix memory leaks in read-cache.c Ingo Molnar
@ 2005-04-14 13:12 ` Ingo Molnar
2 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 13:12 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
this patch fixes a memory leak in write-tree.c's write_tree() function -
we didnt free the temporary output buffer. Depending on the size of the
tree written out this could leak a significant amount of RAM.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- write-tree.c.orig
+++ write-tree.c
@@ -33,12 +33,12 @@ static int write_tree(struct cache_entry
{
unsigned char subdir_sha1[20];
unsigned long size, offset;
- char *buffer;
+ char *buffer0, *buffer;
int i, nr;
/* Guess at some random initial size */
size = 8192;
- buffer = malloc(size);
+ buffer0 = buffer = malloc(size);
offset = ORIG_OFFSET;
nr = 0;
@@ -97,6 +97,8 @@ static int write_tree(struct cache_entry
offset -= i;
write_sha1_file(buffer, offset, returnsha1);
+ free(buffer0);
+
return nr;
}
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [patch] git: fix memory leak #2 in read-cache.c
2005-04-14 12:39 ` [patch] git: fix memory leak #2 " Ingo Molnar
@ 2005-04-14 13:25 ` Ingo Molnar
2005-04-14 14:25 ` Martin Schlemmer
2005-04-14 15:11 ` Linus Torvalds
1 sibling, 1 reply; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 13:25 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds, Martin Schlemmer
* Ingo Molnar <mingo@elte.hu> wrote:
> this patch fixes a memory leak in read-cache.c: when there's cache
> entry collision we should free the previous one.
> + free(active_cache[pos]);
> active_cache[pos] = ce;
i'm having second thoughs about this one: active_cache entries are not
always malloc()-ed - e.g. read_cache() will construct them from the
mmap() of the index file. Which must not be free()d!
one safe solution would be to malloc() all these entries and copy them
over from the index file? Slightly slower but safer and free()-able when
update-cache.c notices a collision. The (tested) patch below does this.
this would also make Martin Schlemmer's update-cache.c fix safe.
(without this second patch, free(active_cache[pos]) might crash, and
that crash is would possibly be remote exploitable via a special
repository that tricks the index file to look in a certain way.)
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- read-cache.c.orig
+++ read-cache.c
@@ -453,10 +453,17 @@ int read_cache(void)
offset = sizeof(*hdr);
for (i = 0; i < hdr->entries; i++) {
- struct cache_entry *ce = map + offset;
+ struct cache_entry *ce = map + offset, *tmp;
offset = offset + ce_size(ce);
- active_cache[i] = ce;
+
+ tmp = malloc(ce_size(ce));
+ if (!tmp)
+ return error("malloc failed");
+ memcpy(tmp, ce, ce_size(ce));
+ active_cache[i] = tmp;
}
+ munmap(map, size);
+
return active_nr;
unmap:
^ permalink raw reply [flat|nested] 22+ messages in thread
* [patch] git: fix memory leak #3 in update-cache.c
2005-04-14 13:03 ` [patch] git: fix memory leaks in update-cache.c Ingo Molnar
2005-04-14 13:08 ` [patch] git: clean up add_file_to_cache() " Ingo Molnar
@ 2005-04-14 13:31 ` Ingo Molnar
1 sibling, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 13:31 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
the patch below fixes a third memory leak in update-cache.c. (the
mmap-ed file needs to be unmapped too) Ontop of the previous
update-cache.c patches.
Ingo
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- update-cache.c.orig
+++ update-cache.c
@@ -32,6 +32,8 @@ static int index_fd(const char *path, in
if (!out || (int)(long)in == -1) {
free(out);
free(metadata);
+ if ((int)(long)in != -1 && size)
+ munmap(in, size);
return -1;
}
@@ -66,6 +68,8 @@ static int index_fd(const char *path, in
free(out);
free(metadata);
+ if (size)
+ munmap(in, size);
return ret;
}
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [patch] git: fix memory leak #2 in read-cache.c
2005-04-14 13:25 ` Ingo Molnar
@ 2005-04-14 14:25 ` Martin Schlemmer
0 siblings, 0 replies; 22+ messages in thread
From: Martin Schlemmer @ 2005-04-14 14:25 UTC (permalink / raw)
To: Ingo Molnar; +Cc: git, Linus Torvalds
[-- Attachment #1: Type: text/plain, Size: 888 bytes --]
On Thu, 2005-04-14 at 15:25 +0200, Ingo Molnar wrote:
> * Ingo Molnar <mingo@elte.hu> wrote:
>
> > this patch fixes a memory leak in read-cache.c: when there's cache
> > entry collision we should free the previous one.
>
> > + free(active_cache[pos]);
> > active_cache[pos] = ce;
>
> i'm having second thoughs about this one: active_cache entries are not
> always malloc()-ed - e.g. read_cache() will construct them from the
> mmap() of the index file. Which must not be free()d!
>
> one safe solution would be to malloc() all these entries and copy them
> over from the index file? Slightly slower but safer and free()-able when
> update-cache.c notices a collision. The (tested) patch below does this.
>
> this would also make Martin Schlemmer's update-cache.c fix safe.
>
Ok, bad me it seems - assumed it was malloc'd.
--
Martin Schlemmer
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [patch] git: fix memory leak #2 in read-cache.c
2005-04-14 12:39 ` [patch] git: fix memory leak #2 " Ingo Molnar
2005-04-14 13:25 ` Ingo Molnar
@ 2005-04-14 15:11 ` Linus Torvalds
2005-04-14 15:14 ` Ingo Molnar
1 sibling, 1 reply; 22+ messages in thread
From: Linus Torvalds @ 2005-04-14 15:11 UTC (permalink / raw)
To: Ingo Molnar; +Cc: git
On Thu, 14 Apr 2005, Ingo Molnar wrote:
>
> this patch fixes a memory leak in read-cache.c: when there's cache entry
> collision we should free the previous one.
As you already noticed "read_cache()" normally just populates the
active-cache with pointers to the mmap'ed "active" file.
Whether that is a good idea or not, I do not know. But I do know that the
active file is the single biggest file we work with (ie 1.6MB in size), so
since _most_ tools just read it and modify a very small number of entries,
it seemed like a good idea.
In other words, if the common case is that we update a couple of entries
in the active cache, we actually saved 1.6MB (+ malloc overhead for the 17
_thousand_ allocations) by my approach.
And the leak? There's none. We never actually update an existing entry
that was allocated with malloc(), unless the user does something stupid.
In other words, the only case where there is a "leak" is when the user
does something like
update-cache file file file file file file ..
with the same file listed several times.
And dammit, the whole point of doing stuff in user space is that the
kernel takes care of business. Unlike kernel work, leaking is ok. You just
have to make sure that it is limited enough to to not be a problem. I'm
saying that in this case we're _better_ off leaking, because the mmap()
trick saves us more memory than the leak can ever leak.
(The command line is limited to 128kB or so, which means that the most
files you _can_ add with a single update-cache is _less_ than the mmap
win).
It was _such_ a relief to program in user mode for a change. Not having to
care about the small stuff is wonderful.
Linus
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [patch] git: fix memory leak #2 in read-cache.c
2005-04-14 15:11 ` Linus Torvalds
@ 2005-04-14 15:14 ` Ingo Molnar
0 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-14 15:14 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
* Linus Torvalds <torvalds@osdl.org> wrote:
> In other words, if the common case is that we update a couple of
> entries in the active cache, we actually saved 1.6MB (+ malloc
> overhead for the 17 _thousand_ allocations) by my approach.
>
> And the leak? There's none. We never actually update an existing entry
> that was allocated with malloc(), unless the user does something
> stupid. In other words, the only case where there is a "leak" is when
> the user does something like
>
> update-cache file file file file file file ..
>
> with the same file listed several times.
fair enough - as long as this is only used in a scripted environment,
and not via some library and not within a repository server, web
backend, etc.
Ingo
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [patch] git: fix 1-byte overflow in show-files.c
2005-04-14 12:53 ` [patch] git: fix 1-byte overflow in show-files.c Ingo Molnar
@ 2005-04-17 23:59 ` Petr Baudis
2005-04-18 8:28 ` Ingo Molnar
0 siblings, 1 reply; 22+ messages in thread
From: Petr Baudis @ 2005-04-17 23:59 UTC (permalink / raw)
To: Ingo Molnar; +Cc: git, Linus Torvalds
Dear diary, on Thu, Apr 14, 2005 at 02:53:54PM CEST, I got a letter
where Ingo Molnar <mingo@elte.hu> told me that...
>
> this patch fixes a 1-byte overflow in show-files.c (looks narrow is is
> probably not exploitable). A specially crafted db object (tree) might
> trigger this overflow.
>
> 'fullname' is an array of 4096+1 bytes, and we do readdir(), which
> produces entries that have strings with a length of 0-255 bytes. With a
> long enough 'base', it's possible to construct a tree with a name in it
> that has directory whose name ends precisely at offset 4095. At that
> point this code:
>
> case DT_DIR:
> memcpy(fullname + baselen + len, "/", 2);
>
> will attempt to append a "/" string to the directory name - resulting in
> a 1-byte overflow (a zero byte is written to offset 4097, which is
> outside the array).
The name ends precisely at offset 4095 with its NUL character:
{PATH_MAX}
Maximum number of bytes in a pathname, including the terminating
null character.
[ http://www.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html ]
So, if I'm not mistaken, '/' will be written at offset 4095 instead of
the NUL and the NUL will be written at 4096. Everything's fine, right?
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [patch] git: fix 1-byte overflow in show-files.c
2005-04-17 23:59 ` Petr Baudis
@ 2005-04-18 8:28 ` Ingo Molnar
0 siblings, 0 replies; 22+ messages in thread
From: Ingo Molnar @ 2005-04-18 8:28 UTC (permalink / raw)
To: Petr Baudis; +Cc: git, Linus Torvalds
* Petr Baudis <pasky@ucw.cz> wrote:
> > will attempt to append a "/" string to the directory name - resulting in
> > a 1-byte overflow (a zero byte is written to offset 4097, which is
> > outside the array).
>
> The name ends precisely at offset 4095 with its NUL character:
>
> {PATH_MAX}
> Maximum number of bytes in a pathname, including the terminating
> null character.
> [ http://www.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html ]
>
> So, if I'm not mistaken, '/' will be written at offset 4095 instead of
> the NUL and the NUL will be written at 4096. Everything's fine, right?
yeah, you are right - ignore this patch.
Ingo
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2005-04-18 8:24 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-14 11:26 [patch] git: fix memory leak in checkout-cache.c Ingo Molnar
2005-04-14 11:35 ` [patch] git: fix memory leak #2 " Ingo Molnar
2005-04-14 11:43 ` [patch] git: cleanup in ls-tree.c Ingo Molnar
2005-04-14 11:54 ` [patch] git: fix memory leaks in read-tree.c Ingo Molnar
2005-04-14 11:58 ` [patch] git: fix rare memory leak in rev-tree.c Ingo Molnar
2005-04-14 12:05 ` [patch] git: report parse_commit() errors " Ingo Molnar
2005-04-14 12:08 ` [patch] git: fix memory leak in show-diff.c Ingo Molnar
2005-04-14 12:18 ` [patch] git: fix overflow in update-cache.c Ingo Molnar
2005-04-14 12:23 ` [patch] cleanup: read_sha1_file() -> malloc_read_sha1_file() Ingo Molnar
2005-04-14 12:53 ` [patch] git: fix 1-byte overflow in show-files.c Ingo Molnar
2005-04-17 23:59 ` Petr Baudis
2005-04-18 8:28 ` Ingo Molnar
2005-04-14 13:03 ` [patch] git: fix memory leaks in update-cache.c Ingo Molnar
2005-04-14 13:08 ` [patch] git: clean up add_file_to_cache() " Ingo Molnar
2005-04-14 13:31 ` [patch] git: fix memory leak #3 " Ingo Molnar
2005-04-14 12:32 ` [patch] git: fix memory leaks in read-cache.c Ingo Molnar
2005-04-14 12:39 ` [patch] git: fix memory leak #2 " Ingo Molnar
2005-04-14 13:25 ` Ingo Molnar
2005-04-14 14:25 ` Martin Schlemmer
2005-04-14 15:11 ` Linus Torvalds
2005-04-14 15:14 ` Ingo Molnar
2005-04-14 13:12 ` [patch] git: fix memory leak in write-tree.c Ingo Molnar
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).