From 639ca5497279607665847f2e3a11064441a8f2a6 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 10 May 2006 12:26:08 -0400 Subject: fix diff-delta bad memory access It cannot be assumed that the given buffer will never be moved when shrinking the allocated memory size with realloc(). So let's ignore that optimization for now. This patch makes Electric Fence happy on Linux. Signed-off-by: Nicolas Pitre Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff-delta.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/diff-delta.c b/diff-delta.c index c618875188..25a798d050 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -199,7 +199,6 @@ struct delta_index * create_delta_index(const void *buf, unsigned long bufsize) entry->next = hash[i]; hash[i] = entry++; hash_count[i]++; - entries--; } } @@ -230,10 +229,6 @@ struct delta_index * create_delta_index(const void *buf, unsigned long bufsize) } free(hash_count); - /* If we didn't use all hash entries, free the unused memory. */ - if (entries) - index = realloc(index, memsize - entries * sizeof(*entry)); - return index; } -- cgit v1.2.3 From 66561f5a776f2343331fff5b98adff1000622f42 Mon Sep 17 00:00:00 2001 From: Dennis Stosberg Date: Thu, 11 May 2006 19:36:32 +0200 Subject: Fix git-pack-objects for 64-bit platforms The offset of an object in the pack is recorded as a 4-byte integer in the index file. When reading the offset from the mmap'ed index in prepare_pack_revindex(), the address is dereferenced as a long*. This works fine as long as the long type is four bytes wide. On NetBSD/sparc64, however, a long is 8 bytes wide and so dereferencing the offset produces garbage. [jc: taking suggestion by Linus to use uint32_t] Signed-off-by: Dennis Stosberg Signed-off-by: Junio C Hamano --- pack-objects.c | 2 +- sha1_file.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pack-objects.c b/pack-objects.c index c0acc460bb..a81d609b26 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -156,7 +156,7 @@ static void prepare_pack_revindex(struct pack_revindex *rix) rix->revindex = xmalloc(sizeof(unsigned long) * (num_ent + 1)); for (i = 0; i < num_ent; i++) { - long hl = *((long *)(index + 24 * i)); + uint32_t hl = *((uint32_t *)(index + 24 * i)); rix->revindex[i] = ntohl(hl); } /* This knows the pack format -- the 20-byte trailer diff --git a/sha1_file.c b/sha1_file.c index f2d33afb27..642c45ad75 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1126,7 +1126,7 @@ int find_pack_entry_one(const unsigned char *sha1, int mi = (lo + hi) / 2; int cmp = memcmp(index + 24 * mi + 4, sha1, 20); if (!cmp) { - e->offset = ntohl(*((int*)(index + 24 * mi))); + e->offset = ntohl(*((uint32_t *)(index + 24 * mi))); memcpy(e->sha1, sha1, 20); e->p = p; return 1; -- cgit v1.2.3 From 618faa1dc7cb5898473861c286391d0a4b043107 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 9 May 2006 19:23:23 -0700 Subject: checkout: use --aggressive when running a 3-way merge (-m). After doing an in-index 3-way merge, we always do the stock "merge-index merge-one-file" without doing anything fancy; use of --aggressive helps performance quite a bit. Signed-off-by: Junio C Hamano --- git-checkout.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-checkout.sh b/git-checkout.sh index 463ed2eaff..a11c939c30 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -144,7 +144,7 @@ else work=`git write-tree` && git read-tree --reset $new && git checkout-index -f -u -q -a && - git read-tree -m -u $old $new $work || exit + git read-tree -m -u --aggressive $old $new $work || exit if result=`git write-tree 2>/dev/null` then -- cgit v1.2.3 From bdf0ef0824ecca427ec04ac047ffe4aaf73ace5a Mon Sep 17 00:00:00 2001 From: sean Date: Sat, 6 May 2006 14:14:02 -0400 Subject: Another config file parsing fix. If the variable we need to store should go into a section that currently only has a single variable (not matching the one we're trying to insert), we will already be into the next section before we notice we've bypassed the correct location to insert the variable. To handle this case we store the current location as soon as we find a variable matching the section of our new variable. This breakage was brought up by Linus. Signed-off-by: Sean Estabrooks Signed-off-by: Junio C Hamano --- config.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.c b/config.c index adb5ce476a..0f518c957c 100644 --- a/config.c +++ b/config.c @@ -336,8 +336,10 @@ static int store_aux(const char* key, const char* value) store.state = KEY_SEEN; store.seen++; } else if (strrchr(key, '.') - key == store.baselen && - !strncmp(key, store.key, store.baselen)) + !strncmp(key, store.key, store.baselen)) { store.state = SECTION_SEEN; + store.offset[store.seen] = ftell(config_file); + } } return 0; } -- cgit v1.2.3 From d14f776402d9f7040cc71ff6e3b992b2e019526a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 9 May 2006 12:24:02 -0700 Subject: git config syntax updates This updates the hierarchical section name syntax to [section+""] where the only rule for "randomstring" is that it can't contain a newline, and if you really want to insert a double-quote, you do it with \". It turns that into the section name "secion.randomstring". The "section" part is still case insensitive, but the "randomstring" part is case sensitive. So you could use this for things like [email "torvalds@osdl.org"] name = Linus Torvalds if you wanted to do the "email->name" conversion as part of the config file format (I'm not claiming that is sensible, I'm just giving it as an insane example). That would show up as the association email.torvalds@osdl.org.name -> Linus Torvalds which is easy to parse (the "." in the email _looks_ ambiguous, but it isn't: you know that there will always be a single key-name, so you find the key name with "strrchr(name, '.')" and things are entirely unambiguous). Repo-config is updated to be able to parse the new format, and also write things out in the new format. [jc: rolled two patches from Linus and one fix-up from Sean into one, with additional adjustments for t/t1300 test to check the case insensitiveness of section base and variable and case sensitiveness of the extended section part. Then stripped some part off to make the result applicable to the stale 1.3.X series that does not have recent enhancements. ] Signed-off-by: Linus Torvalds Signed-off-by: Sean Estabrooks Signed-off-by: Junio C Hamano --- config.c | 94 +++++++++++++++++++++++++++++++++++++++++++------- repo-config.c | 10 +++--- t/t1300-repo-config.sh | 6 ++-- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/config.c b/config.c index 0f518c957c..0248c6d8a5 100644 --- a/config.c +++ b/config.c @@ -134,6 +134,41 @@ static int get_value(config_fn_t fn, char *name, unsigned int len) return fn(name, value); } +static int get_extended_base_var(char *name, int baselen, int c) +{ + do { + if (c == '\n') + return -1; + c = get_next_char(); + } while (isspace(c)); + + /* We require the format to be '[base "extension"]' */ + if (c != '"') + return -1; + name[baselen++] = '.'; + + for (;;) { + int c = get_next_char(); + if (c == '\n') + return -1; + if (c == '"') + break; + if (c == '\\') { + c = get_next_char(); + if (c == '\n') + return -1; + } + name[baselen++] = c; + if (baselen > MAXNAME / 2) + return -1; + } + + /* Final ']' */ + if (get_next_char() != ']') + return -1; + return baselen; +} + static int get_base_var(char *name) { int baselen = 0; @@ -144,6 +179,8 @@ static int get_base_var(char *name) return -1; if (c == ']') return baselen; + if (isspace(c)) + return get_extended_base_var(name, baselen, c); if (!isalnum(c) && c != '.') return -1; if (baselen > MAXNAME / 2) @@ -335,10 +372,12 @@ static int store_aux(const char* key, const char* value) store.offset[store.seen] = ftell(config_file); store.state = KEY_SEEN; store.seen++; - } else if (strrchr(key, '.') - key == store.baselen && + } else { + if (strrchr(key, '.') - key == store.baselen && !strncmp(key, store.key, store.baselen)) { store.state = SECTION_SEEN; store.offset[store.seen] = ftell(config_file); + } } } return 0; @@ -346,8 +385,30 @@ static int store_aux(const char* key, const char* value) static void store_write_section(int fd, const char* key) { + const char *dot = strchr(key, '.'); + int len1 = store.baselen, len2 = -1; + + dot = strchr(key, '.'); + if (dot) { + int dotlen = dot - key; + if (dotlen < len1) { + len2 = len1 - dotlen - 1; + len1 = dotlen; + } + } + write(fd, "[", 1); - write(fd, key, store.baselen); + write(fd, key, len1); + if (len2 >= 0) { + write(fd, " \"", 2); + while (--len2 >= 0) { + unsigned char c = *++dot; + if (c == '"') + write(fd, "\\", 1); + write(fd, &c, 1); + } + write(fd, "\"", 1); + } write(fd, "]\n", 2); } @@ -421,7 +482,7 @@ int git_config_set(const char* key, const char* value) int git_config_set_multivar(const char* key, const char* value, const char* value_regex, int multi_replace) { - int i; + int i, dot; int fd = -1, in_fd; int ret; char* config_filename = strdup(git_path("config")); @@ -446,16 +507,23 @@ int git_config_set_multivar(const char* key, const char* value, * Validate the key and while at it, lower case it for matching. */ store.key = (char*)malloc(strlen(key)+1); - for (i = 0; key[i]; i++) - if (i != store.baselen && - ((!isalnum(key[i]) && key[i] != '.') || - (i == store.baselen+1 && !isalpha(key[i])))) { - fprintf(stderr, "invalid key: %s\n", key); - free(store.key); - ret = 1; - goto out_free; - } else - store.key[i] = tolower(key[i]); + dot = 0; + for (i = 0; key[i]; i++) { + unsigned char c = key[i]; + if (c == '.') + dot = 1; + /* Leave the extended basename untouched.. */ + if (!dot || i > store.baselen) { + if (!isalnum(c) || (i == store.baselen+1 && !isalpha(c))) { + fprintf(stderr, "invalid key: %s\n", key); + free(store.key); + ret = 1; + goto out_free; + } + c = tolower(c); + } + store.key[i] = c; + } store.key[i] = 0; /* diff --git a/repo-config.c b/repo-config.c index c5ebb7668a..58b6c5284f 100644 --- a/repo-config.c +++ b/repo-config.c @@ -48,11 +48,13 @@ static int show_config(const char* key_, const char* value_) static int get_value(const char* key_, const char* regex_) { int i; + char *tl; - key = malloc(strlen(key_)+1); - for (i = 0; key_[i]; i++) - key[i] = tolower(key_[i]); - key[i] = 0; + key = strdup(key_); + for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl) + *tl = tolower(*tl); + for (tl=key; *tl && *tl != '.'; ++tl) + *tl = tolower(*tl); if (regex_) { if (regex_[0] == '!') { diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index ab4dd5c4ce..028d15956b 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -229,7 +229,7 @@ test_expect_failure 'invalid key' 'git-repo-config inval.2key blabla' test_expect_success 'correct key' 'git-repo-config 123456.a123 987' test_expect_success 'hierarchical section' \ - 'git-repo-config 1.2.3.alpha beta' + 'git-repo-config Version.1.2.3eX.Alpha beta' cat > expect << EOF [beta] ; silly comment # another comment @@ -241,8 +241,8 @@ noIndent= sillyValue ; 'nother silly comment NoNewLine = wow2 for me [123456] a123 = 987 -[1.2.3] - alpha = beta +[Version "1.2.3eX"] + Alpha = beta EOF test_expect_success 'hierarchical section value' 'cmp .git/config expect' -- cgit v1.2.3