Merge branch 'master' of git://github.com/git-l10n/git-po
authorJiang Xin <worldhello.net@gmail.com>
Sat, 12 Mar 2016 14:04:39 +0000 (22:04 +0800)
committerJiang Xin <worldhello.net@gmail.com>
Sat, 12 Mar 2016 14:04:39 +0000 (22:04 +0800)
* 'master' of git://github.com/git-l10n/git-po:
l10n: zh_CN: for git v2.8.0 l10n round 1
l10n: de.po: translate 48 new messages
l10n: de.po: translate "command" as "Befehl"
l10n: de.po: fix interactive rebase message
l10n: de.po: add space to abbreviation "z. B."
l10n: de.po: fix typo
l10n: TEAMS: update Ralf Thielow's email address
l10n: sv.po: Update Swedish translation (2509t0f0u)
l10n: sv.po: Fix inconsistent translation of "progress meter"
l10n: ko.po: Update Korean translation
l10n: ru.po: update Russian translation
l10n: vi.po (2509t): Updated Vietnamese translation
l10n: fr.po v2.8.0 round 1 2509t
l10n: fr.po: Correct case in sentence
l10n: git.pot: v2.8.0 round 1 (48 new, 16 removed)

28 files changed:
Documentation/RelNotes/2.7.3.txt [new file with mode: 0644]
Documentation/RelNotes/2.8.0.txt
Documentation/git-ls-files.txt
Documentation/git-rebase.txt
Documentation/git.txt
Documentation/gitignore.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
builtin/checkout.c
builtin/clone.c
builtin/index-pack.c
cache.h
compat/mingw.c
compat/win32/pthread.h
config.mak.uname
http.c
ref-filter.c
run-command.c
run-command.h
sha1_file.c
submodule.c
t/lib-httpd/apache.conf
t/t0001-init.sh
t/t5313-pack-bounds-checks.sh [new file with mode: 0755]
t/t5510-fetch.sh
t/t9700/test.pl
test-run-command.c
trailer.c
diff --git a/Documentation/RelNotes/2.7.3.txt b/Documentation/RelNotes/2.7.3.txt
new file mode 100644 (file)
index 0000000..6adf038
--- /dev/null
@@ -0,0 +1,62 @@
+Git v2.7.3 Release Notes
+========================
+
+Fixes since v2.7.2
+------------------
+
+ * Traditionally, the tests that try commands that work on the
+   contents in the working tree were named with "worktree" in their
+   filenames, but with the recent addition of "git worktree"
+   subcommand, whose tests are also named similarly, it has become
+   harder to tell them apart.  The traditional tests have been renamed
+   to use "work-tree" instead in an attempt to differentiate them.
+
+ * Many codepaths forget to check return value from git_config_set();
+   the function is made to die() to make sure we do not proceed when
+   setting a configuration variable failed.
+
+ * Handling of errors while writing into our internal asynchronous
+   process has been made more robust, which reduces flakiness in our
+   tests.
+
+ * "git show 'HEAD:Foo[BAR]Baz'" did not interpret the argument as a
+   rev, i.e. the object named by the the pathname with wildcard
+   characters in a tree object.
+
+ * "git rev-parse --git-common-dir" used in the worktree feature
+   misbehaved when run from a subdirectory.
+
+ * The "v(iew)" subcommand of the interactive "git am -i" command was
+   broken in 2.6.0 timeframe when the command was rewritten in C.
+
+ * "git merge-tree" used to mishandle "both sides added" conflict with
+   its own "create a fake ancestor file that has the common parts of
+   what both sides have added and do a 3-way merge" logic; this has
+   been updated to use the usual "3-way merge with an empty blob as
+   the fake common ancestor file" approach used in the rest of the
+   system.
+
+ * The memory ownership rule of fill_textconv() API, which was a bit
+   tricky, has been documented a bit better.
+
+ * The documentation did not clearly state that the 'simple' mode is
+   now the default for "git push" when push.default configuration is
+   not set.
+
+ * Recent versions of GNU grep are pickier when their input contains
+   arbitrary binary data, which some of our tests uses.  Rewrite the
+   tests to sidestep the problem.
+
+ * A helper function "git submodule" uses since v2.7.0 to list the
+   modules that match the pathspec argument given to its subcommands
+   (e.g. "submodule add <repo> <path>") has been fixed.
+
+ * "git config section.var value" to set a value in per-repository
+   configuration file failed when it was run outside any repository,
+   but didn't say the reason correctly.
+
+ * The code to read the pack data using the offsets stored in the pack
+   idx file has been made more carefully check the validity of the
+   data in the idx.
+
+Also includes documentation and test updates.
index 290774e61a398cf335763cb55814421c95595e0f..14b6c70ed6a64cae8d75fd0de863f66597c67da8 100644 (file)
@@ -233,6 +233,13 @@ Performance, Internal Implementation, Development Support etc.
  * There is a new DEVELOPER knob that enables many compiler warning
    options in the Makefile.
 
+ * The way the test scripts configure the Apache web server has been
+   updated to work also for Apache 2.4 running on RedHat derived
+   distros.
+
+ * Out of maintenance gcc on OSX 10.6 fails to compile the code in
+   'master'; work it around by using clang by default on the platform.
+
 
 Also contains various documentation updates and code clean-ups.
 
@@ -274,6 +281,11 @@ notes for details).
    listing and sparse checkout selection areas in 2.7.0; the change
    that is responsible for the regression has been reverted.
 
+ * Another try to improve the ignore mechanism that lets you say "this
+   is excluded" and then later say "oh, no, this part (that is a
+   subset of the previous part) is not excluded".  This has still a
+   known limitation, though.
+
  * Some codepaths used fopen(3) when opening a fixed path in $GIT_DIR
    (e.g. COMMIT_EDITMSG) that is meant to be left after the command is
    done.  This however did not work well if the repository is set to
@@ -365,10 +377,6 @@ notes for details).
    misbehaved when run from a subdirectory.
    (merge 17f1365 nd/git-common-dir-fix later to maint).
 
- * Another try to add support to the ignore mechanism that lets you
-   say "this is excluded" and then later say "oh, no, this part (that
-   is a subset of the previous part) is not excluded".
-
  * "git worktree add -B <branchname>" did not work.
 
  * The "v(iew)" subcommand of the interactive "git am -i" command was
@@ -410,6 +418,11 @@ notes for details).
    but didn't say the reason correctly.
    (merge 638fa62 js/config-set-in-non-repository later to maint).
 
+ * The code to read the pack data using the offsets stored in the pack
+   idx file has been made more carefully check the validity of the
+   data in the idx.
+   (merge 7465feb jk/pack-idx-corruption-safety later to maint).
+
  * Other minor clean-ups and documentation updates
    (merge f459823 ak/extract-argv0-last-dir-sep later to maint).
    (merge 63ca1c0 ak/git-strip-extension-from-dashed-command later to maint).
index 0e08f567a163571c7d8f2a4c10984691f5aba566..75c3f4157d845876a91f04f955878a3affc9bd6e 100644 (file)
@@ -155,7 +155,7 @@ a space) at the start of each line:
        <eolinfo> is either "-text", "none", "lf", "crlf", "mixed" or "".
 +
 "" means the file is not a regular file, it is not in the index or
-not accessable in the working tree.
+not accessible in the working tree.
 +
 <eolattr> is the attribute that is used when checking out or committing,
 it is either "", "-text", "text", "text=auto", "text eol=lf", "text eol=crlf".
index 6cca8bb51dcabd47474ad63d908d7ec5d06d8703..6ed610a031eeec7320adbbb4a627dc4997499e56 100644 (file)
@@ -3,7 +3,7 @@ git-rebase(1)
 
 NAME
 ----
-git-rebase - Forward-port local commits to the updated upstream head
+git-rebase - Reapply commits on top of another base tip
 
 SYNOPSIS
 --------
index 2754af8f7782d4a13fce4f5752737e3106491f22..951b24661e45ffe8b11444166e3a6cc7a3c6e1d2 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.7.2/git.html[documentation for release 2.7.2]
+* link:v2.7.3/git.html[documentation for release 2.7.3]
 
 * release notes for
+  link:RelNotes/2.7.3.txt[2.7.3],
   link:RelNotes/2.7.2.txt[2.7.2],
   link:RelNotes/2.7.1.txt[2.7.1],
   link:RelNotes/2.7.0.txt[2.7].
index 3ded6fdc9972bb72a0efea73f0a2c73ae3e9906d..91d1ce2a89e6a180b934ab8836c41affdb2751ce 100644 (file)
@@ -148,7 +148,43 @@ excluded, the following conditions must be met:
    be in the same .gitignore file.
 
  - The directory part in the re-include rules must be literal (i.e. no
-   wildcards)
+   wildcards and has to start with a `/`).
+
+A re-inclusion of a directory makes all files in the directory
+unignored.  For example, suppose you have files `.gitignore`,
+`dir/file1`, `dir/file2`, and `dir/file3`, and have the following in
+your `.gitignore`:
+
+----------------
+# .gitignore is not mentioned in .gitignore
+*
+!/dir
+# dir/file1 is not mentioned in .gitignore
+dir/file2
+!dir/file3
+----------------
+
+Then:
+
+ - `.gitignore` gets ignored, because it matches the `*` at the top
+   level;
+
+ - `dir/file1` does not get ignored, because `/dir` marks everything
+   underneath `dir/` directory to be 're-included' unless otherwise
+   specified;
+
+ - `dir/file2` gets ignored, because `dir/file2` matches it.
+
+ - `dir/file3` does not get ignored, because `!dir/file3` matches it.
+   Note that the entry `!dir/file3` is redundant because everything
+   underneath `dir/` is marked to be 're-included' already.
+
+Some earlier versions of Git treated `!/dir` above differently in
+that it did not cause the paths under it unignored (but merely told
+Git that patterns that begin with dir/ should not be ignored), but
+this has been corrected to be consistent with `/dir` that says "the
+directory `dir/` and everything below are ignored."
+
 
 EXAMPLES
 --------
index ec6bacfcdfa8418b5e24a09c04091e6b92119d46..5e074545729fbd938efaa65311f8437b2ca1bcdf 100644 (file)
@@ -2134,7 +2134,7 @@ browsing the repository using gitweb. The default server when using
 instaweb is lighttpd.
 
 See the file gitweb/INSTALL in the Git source tree and
-linkgit:gitweb[1] for instructions on details setting up a permament
+linkgit:gitweb[1] for instructions on details setting up a permanent
 installation with a CGI or Perl capable server.
 
 [[how-to-get-a-git-repository-with-minimal-history]]
index b872b6e7d6e5067b7f080217a66f0b9d45c4931b..b373d8ae8ddfd828951c5d93cb9032de0071dfde 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.8.0-rc0
+DEF_VER=v2.8.0-rc2
 
 LF='
 '
index cfa66e25eb0838ba70d87d3008c6d3c57e363bd1..efcbd8f6b5e0b7d551c88c02b6d7d3069a47944d 100644 (file)
@@ -662,7 +662,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
                }
        } else if (new->path) { /* Switch branches. */
                if (create_symref("HEAD", new->path, msg.buf) < 0)
-                       die("unable to update HEAD");
+                       die(_("unable to update HEAD"));
                if (!opts->quiet) {
                        if (old->path && !strcmp(new->path, old->path)) {
                                if (opts->new_branch_force)
index 9ac6c014427908324c4a2d7ca79dbc858f5b622e..661639255c564acf3f811e20a0ca3141805cde5d 100644 (file)
@@ -236,8 +236,8 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
        strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
 
        if (!len || (len == 1 && *start == '/'))
-           die("No directory name could be guessed.\n"
-               "Please specify a directory on the command line");
+               die(_("No directory name could be guessed.\n"
+                     "Please specify a directory on the command line"));
 
        if (is_bare)
                dir = xstrfmt("%.*s.git", (int)len, start);
@@ -644,7 +644,7 @@ static void update_remote_refs(const struct ref *refs,
                if (create_symref(head_ref.buf,
                                  remote_head_points_at->peer_ref->name,
                                  msg) < 0)
-                       die("unable to update %s", head_ref.buf);
+                       die(_("unable to update %s"), head_ref.buf);
                strbuf_release(&head_ref);
        }
 }
@@ -656,7 +656,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
        if (our && skip_prefix(our->name, "refs/heads/", &head)) {
                /* Local default branch link */
                if (create_symref("HEAD", our->name, NULL) < 0)
-                       die("unable to update HEAD");
+                       die(_("unable to update HEAD"));
                if (!option_bare) {
                        update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
                                   UPDATE_REFS_DIE_ON_ERR);
@@ -750,7 +750,7 @@ static void write_config(struct string_list *config)
        for (i = 0; i < config->nr; i++) {
                if (git_config_parse_parameter(config->items[i].string,
                                               write_one_config, NULL) < 0)
-                       die("unable to write parameters to config file");
+                       die(_("unable to write parameters to config file"));
        }
 }
 
index 193908a619307ff38bacb212bd0450aae53e2510..45245199aebafc7fdb8eb96197dacd86c422c413 100644 (file)
@@ -1514,6 +1514,7 @@ static void read_v2_anomalous_offsets(struct packed_git *p,
                if (!(off & 0x80000000))
                        continue;
                off = off & 0x7fffffff;
+               check_pack_index_ptr(p, &idx2[off * 2]);
                if (idx2[off * 2])
                        continue;
                /*
diff --git a/cache.h b/cache.h
index d7ff46ec4a016c6ab7d233b9d4a196ecde623528..b829410f6da0afc14353b4621d2fdf874181a9f7 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1369,6 +1369,16 @@ extern void free_pack_by_name(const char *);
 extern void clear_delta_base_cache(void);
 extern struct packed_git *add_packed_git(const char *path, size_t path_len, int local);
 
+/*
+ * Make sure that a pointer access into an mmap'd index file is within bounds,
+ * and can provide at least 8 bytes of data.
+ *
+ * Note that this is only necessary for variable-length segments of the file
+ * (like the 64-bit extended offset table), as we compare the size to the
+ * fixed-length parts when we open the file.
+ */
+extern void check_pack_index_ptr(const struct packed_git *p, const void *ptr);
+
 /*
  * Return the SHA-1 of the nth object within the specified packfile.
  * Open the index if it is not already open.  The return value points
index cfedcf9656549050c1d97ab69000d4279d1b0b5e..54c82ecf201dde2c317efe6862173c1b40f2552d 100644 (file)
@@ -1069,7 +1069,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
                        free(quoted);
        }
 
-       wargs = xmalloc_array(st_add(st_mult(2, args.len), 1), sizeof(wchar_t));
+       ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
        xutftowcs(wargs, args.buf, 2 * args.len + 1);
        strbuf_release(&args);
 
index 20b35a283ca71070086728384fffadf98aa17bba..b6ed9e74621fe0bc506beb893e477bff26e88756 100644 (file)
@@ -78,7 +78,7 @@ extern int win32_pthread_join(pthread_t *thread, void **value_ptr);
 #define pthread_equal(t1, t2) ((t1).tid == (t2).tid)
 extern pthread_t pthread_self(void);
 
-static inline int pthread_exit(void *ret)
+static inline void NORETURN pthread_exit(void *ret)
 {
        ExitThread((DWORD)(intptr_t)ret);
 }
index d6f7980bb91ab7d1e4a02a91407bd8e38461671b..4c68e078e7ac4a9584b2782f278b00fcbe594505 100644 (file)
@@ -102,6 +102,9 @@ ifeq ($(uname_S),Darwin)
        ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2)
                NO_STRLCPY = YesPlease
        endif
+       ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -eq 10 && echo 1),1)
+               CC = clang
+       endif
        ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -ge 11 && echo 1),1)
                HAVE_GETDELIM = YesPlease
        endif
diff --git a/http.c b/http.c
index 1d5e3bbd11ae0e7dc0e682d3914e07cc13a0ce14..69da4454d8f754598d0316d0e1cb34870aba2b8e 100644 (file)
--- a/http.c
+++ b/http.c
@@ -70,6 +70,7 @@ static long curl_low_speed_limit = -1;
 static long curl_low_speed_time = -1;
 static int curl_ftp_no_epsv;
 static const char *curl_http_proxy;
+static const char *curl_no_proxy;
 static const char *http_proxy_authmethod;
 static struct {
        const char *name;
@@ -624,6 +625,11 @@ static CURL *get_curl_handle(void)
                }
 
                curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
+#if LIBCURL_VERSION_NUM >= 0x071304
+               var_override(&curl_no_proxy, getenv("NO_PROXY"));
+               var_override(&curl_no_proxy, getenv("no_proxy"));
+               curl_easy_setopt(result, CURLOPT_NOPROXY, curl_no_proxy);
+#endif
        }
        init_curl_proxy_auth(result);
 
index bb79d6b9cc0f5aec16eb1dffb842910ba55e99ab..bc551a752c460cd4751034b3d69d7e9b5dfc775e 100644 (file)
@@ -74,14 +74,14 @@ static void remote_ref_atom_parser(struct used_atom *atom, const char *arg)
 static void body_atom_parser(struct used_atom *atom, const char *arg)
 {
        if (arg)
-               die("%%(body) does not take arguments");
+               die(_("%%(body) does not take arguments"));
        atom->u.contents.option = C_BODY_DEP;
 }
 
 static void subject_atom_parser(struct used_atom *atom, const char *arg)
 {
        if (arg)
-               die("%%(subject) does not take arguments");
+               die(_("%%(subject) does not take arguments"));
        atom->u.contents.option = C_SUB;
 }
 
@@ -241,7 +241,7 @@ int parse_ref_filter_atom(const char *atom, const char *ep)
        if (*sp == '*' && sp < ep)
                sp++; /* deref */
        if (ep <= sp)
-               die("malformed field name: %.*s", (int)(ep-atom), atom);
+               die(_("malformed field name: %.*s"), (int)(ep-atom), atom);
 
        /* Do we have the atom already used elsewhere? */
        for (i = 0; i < used_atom_cnt; i++) {
@@ -267,7 +267,7 @@ int parse_ref_filter_atom(const char *atom, const char *ep)
        }
 
        if (ARRAY_SIZE(valid_atom) <= i)
-               die("unknown field name: %.*s", (int)(ep-atom), atom);
+               die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
 
        /* Add it in, including the deref prefix */
        at = used_atom_cnt;
@@ -421,7 +421,7 @@ int verify_ref_format(const char *format)
                int at;
 
                if (!ep)
-                       return error("malformed format string %s", sp);
+                       return error(_("malformed format string %s"), sp);
                /* sp points at "%(" and ep points at the closing ")" */
                at = parse_ref_filter_atom(sp + 2, ep);
                cp = ep + 1;
@@ -875,12 +875,12 @@ static const char *strip_ref_components(const char *refname, const char *nr_arg)
        const char *start = refname;
 
        if (nr < 1 || *end != '\0')
-               die(":strip= requires a positive integer argument");
+               die(_(":strip= requires a positive integer argument"));
 
        while (remaining) {
                switch (*start++) {
                case '\0':
-                       die("ref '%s' does not have %ld components to :strip",
+                       die(_("ref '%s' does not have %ld components to :strip"),
                            refname, nr);
                case '/':
                        remaining--;
@@ -1043,7 +1043,7 @@ static void populate_value(struct ref_array_item *ref)
                        else if (skip_prefix(formatp, "strip=", &arg))
                                refname = strip_ref_components(refname, arg);
                        else
-                               die("unknown %.*s format %s",
+                               die(_("unknown %.*s format %s"),
                                    (int)(formatp - name), name, formatp);
                }
 
@@ -1063,10 +1063,10 @@ static void populate_value(struct ref_array_item *ref)
  need_obj:
        buf = get_obj(ref->objectname, &obj, &size, &eaten);
        if (!buf)
-               die("missing object %s for %s",
+               die(_("missing object %s for %s"),
                    sha1_to_hex(ref->objectname), ref->refname);
        if (!obj)
-               die("parse_object_buffer failed on %s for %s",
+               die(_("parse_object_buffer failed on %s for %s"),
                    sha1_to_hex(ref->objectname), ref->refname);
 
        grab_values(ref->value, 0, obj, buf, size);
@@ -1094,10 +1094,10 @@ static void populate_value(struct ref_array_item *ref)
         */
        buf = get_obj(tagged, &obj, &size, &eaten);
        if (!buf)
-               die("missing object %s for %s",
+               die(_("missing object %s for %s"),
                    sha1_to_hex(tagged), ref->refname);
        if (!obj)
-               die("parse_object_buffer failed on %s for %s",
+               die(_("parse_object_buffer failed on %s for %s"),
                    sha1_to_hex(tagged), ref->refname);
        grab_values(ref->value, 1, obj, buf, size);
        if (!eaten)
@@ -1370,12 +1370,12 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
        unsigned int kind;
 
        if (flag & REF_BAD_NAME) {
-               warning("ignoring ref with broken name %s", refname);
+               warning(_("ignoring ref with broken name %s"), refname);
                return 0;
        }
 
        if (flag & REF_ISBROKEN) {
-               warning("ignoring broken ref %s", refname);
+               warning(_("ignoring broken ref %s"), refname);
                return 0;
        }
 
index 863dad52f1913d8fa20fccd23fc527580c6fcaf7..c72601056cf5ae7be2593ae89af4effc26a1b043 100644 (file)
@@ -902,35 +902,18 @@ struct parallel_processes {
        struct strbuf buffered_output; /* of finished children */
 };
 
-static int default_start_failure(struct child_process *cp,
-                                struct strbuf *err,
+static int default_start_failure(struct strbuf *err,
                                 void *pp_cb,
                                 void *pp_task_cb)
 {
-       int i;
-
-       strbuf_addstr(err, "Starting a child failed:");
-       for (i = 0; cp->argv[i]; i++)
-               strbuf_addf(err, " %s", cp->argv[i]);
-
        return 0;
 }
 
 static int default_task_finished(int result,
-                                struct child_process *cp,
                                 struct strbuf *err,
                                 void *pp_cb,
                                 void *pp_task_cb)
 {
-       int i;
-
-       if (!result)
-               return 0;
-
-       strbuf_addf(err, "A child failed with return code %d:", result);
-       for (i = 0; cp->argv[i]; i++)
-               strbuf_addf(err, " %s", cp->argv[i]);
-
        return 0;
 }
 
@@ -1048,8 +1031,7 @@ static int pp_start_one(struct parallel_processes *pp)
        pp->children[i].process.no_stdin = 1;
 
        if (start_command(&pp->children[i].process)) {
-               code = pp->start_failure(&pp->children[i].process,
-                                        &pp->children[i].err,
+               code = pp->start_failure(&pp->children[i].err,
                                         pp->data,
                                         &pp->children[i].data);
                strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
@@ -1117,7 +1099,7 @@ static int pp_collect_finished(struct parallel_processes *pp)
 
                code = finish_command(&pp->children[i].process);
 
-               code = pp->task_finished(code, &pp->children[i].process,
+               code = pp->task_finished(code,
                                         &pp->children[i].err, pp->data,
                                         &pp->children[i].data);
 
index 42917e8618ea469ff56d52704794b6e3bc86cf97..3d1e59e26e33d062a10698fc139f7fc0f4ae14ec 100644 (file)
@@ -159,8 +159,7 @@ typedef int (*get_next_task_fn)(struct child_process *cp,
  * To send a signal to other child processes for abortion, return
  * the negative signal number.
  */
-typedef int (*start_failure_fn)(struct child_process *cp,
-                               struct strbuf *err,
+typedef int (*start_failure_fn)(struct strbuf *err,
                                void *pp_cb,
                                void *pp_task_cb);
 
@@ -179,7 +178,6 @@ typedef int (*start_failure_fn)(struct child_process *cp,
  * the negative signal number.
  */
 typedef int (*task_finished_fn)(int result,
-                               struct child_process *cp,
                                struct strbuf *err,
                                void *pp_cb,
                                void *pp_task_cb);
@@ -193,9 +191,8 @@ typedef int (*task_finished_fn)(int result,
  * (both stdout and stderr) is routed to stderr in a manner that output
  * from different tasks does not interleave.
  *
- * If start_failure_fn or task_finished_fn are NULL, default handlers
- * will be used. The default handlers will print an error message on
- * error without issuing an emergency stop.
+ * start_failure_fn and task_finished_fn can be NULL to omit any
+ * special handling.
  */
 int run_processes_parallel(int n,
                           get_next_task_fn,
index 02517009c15ffe5ef8bc8174805a9746e809eeab..d0f2aa029b14451d4ffe669d48602c55060b9f42 100644 (file)
@@ -1076,6 +1076,8 @@ unsigned char *use_pack(struct packed_git *p,
                die("packfile %s cannot be accessed", p->pack_name);
        if (offset > (p->pack_size - 20))
                die("offset beyond end of packfile (truncated pack?)");
+       if (offset < 0)
+               die(_("offset before end of packfile (broken .idx?)"));
 
        if (!win || !in_window(win, offset)) {
                if (win)
@@ -2448,6 +2450,20 @@ const unsigned char *nth_packed_object_sha1(struct packed_git *p,
        }
 }
 
+void check_pack_index_ptr(const struct packed_git *p, const void *vptr)
+{
+       const unsigned char *ptr = vptr;
+       const unsigned char *start = p->index_data;
+       const unsigned char *end = start + p->index_size;
+       if (ptr < start)
+               die(_("offset before start of pack index for %s (corrupt index?)"),
+                   p->pack_name);
+       /* No need to check for underflow; .idx files must be at least 8 bytes */
+       if (ptr >= end - 8)
+               die(_("offset beyond end of pack index for %s (truncated index?)"),
+                   p->pack_name);
+}
+
 off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
 {
        const unsigned char *index = p->index_data;
@@ -2461,6 +2477,7 @@ off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
                if (!(off & 0x80000000))
                        return off;
                index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
+               check_pack_index_ptr(p, index);
                return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
                                   ntohl(*((uint32_t *)(index + 4)));
        }
index 24fb81ac62e2161e79cbd5ab1f2a241663c2a3a1..62c4356c50d4a41381336559f4e9af27e520ad0d 100644 (file)
@@ -705,8 +705,7 @@ static int get_next_submodule(struct child_process *cp,
        return 0;
 }
 
-static int fetch_start_failure(struct child_process *cp,
-                              struct strbuf *err,
+static int fetch_start_failure(struct strbuf *err,
                               void *cb, void *task_cb)
 {
        struct submodule_parallel_fetch *spf = cb;
@@ -716,8 +715,8 @@ static int fetch_start_failure(struct child_process *cp,
        return 0;
 }
 
-static int fetch_finish(int retvalue, struct child_process *cp,
-                       struct strbuf *err, void *cb, void *task_cb)
+static int fetch_finish(int retvalue, struct strbuf *err,
+                       void *cb, void *task_cb)
 {
        struct submodule_parallel_fetch *spf = cb;
 
index 7d15e6d44c83f6b37297ae01a2998825e313b9b2..f667e7ce2f33dba0c10764f2f62101685d74cf3d 100644 (file)
@@ -64,6 +64,9 @@ LockFile accept.lock
 <IfModule !mod_mpm_prefork.c>
        LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
 </IfModule>
+<IfModule !mod_unixd.c>
+       LoadModule unixd_module modules/mod_unixd.so
+</IfModule>
 </IfVersion>
 
 PassEnv GIT_VALGRIND
index 295aa5949a13baeb8cafff0a6782f6e49e68a075..a5b9e7a4c7e85a2f09718ee7618ae6fb48c600fe 100755 (executable)
@@ -88,19 +88,17 @@ test_expect_success 'plain nested in bare through aliased command' '
 '
 
 test_expect_success 'No extra GIT_* on alias scripts' '
-       (
-               env | sed -ne "/^GIT_/s/=.*//p" &&
-               echo GIT_PREFIX &&        # setup.c
-               echo GIT_TEXTDOMAINDIR    # wrapper-for-bin.sh
-       ) | sort | uniq >expected &&
-       cat <<-\EOF >script &&
-       #!/bin/sh
-       env | sed -ne "/^GIT_/s/=.*//p" | sort >actual
-       exit 0
+       write_script script <<-\EOF &&
+       env |
+               sed -n \
+                       -e "/^GIT_PREFIX=/d" \
+                       -e "/^GIT_TEXTDOMAINDIR=/d" \
+                       -e "/^GIT_/s/=.*//p" |
+               sort
        EOF
-       chmod 755 script &&
+       ./script >expected &&
        git config alias.script \!./script &&
-       ( mkdir sub && cd sub && git script ) &&
+       ( mkdir sub && cd sub && git script >../actual ) &&
        test_cmp expected actual
 '
 
diff --git a/t/t5313-pack-bounds-checks.sh b/t/t5313-pack-bounds-checks.sh
new file mode 100755 (executable)
index 0000000..a8a587a
--- /dev/null
@@ -0,0 +1,179 @@
+#!/bin/sh
+
+test_description='bounds-checking of access to mmapped on-disk file formats'
+. ./test-lib.sh
+
+clear_base () {
+       test_when_finished 'restore_base' &&
+       rm -f $base
+}
+
+restore_base () {
+       cp base-backup/* .git/objects/pack/
+}
+
+do_pack () {
+       pack_objects=$1; shift
+       sha1=$(
+               for i in $pack_objects
+               do
+                       echo $i
+               done | git pack-objects "$@" .git/objects/pack/pack
+       ) &&
+       pack=.git/objects/pack/pack-$sha1.pack &&
+       idx=.git/objects/pack/pack-$sha1.idx &&
+       chmod +w $pack $idx &&
+       test_when_finished 'rm -f "$pack" "$idx"'
+}
+
+munge () {
+       printf "$3" | dd of="$1" bs=1 conv=notrunc seek=$2
+}
+
+# Offset in a v2 .idx to its initial and extended offset tables. For an index
+# with "nr" objects, this is:
+#
+#   magic(4) + version(4) + fan-out(4*256) + sha1s(20*nr) + crc(4*nr),
+#
+# for the initial, and another ofs(4*nr) past that for the extended.
+#
+ofs_table () {
+       echo $((4 + 4 + 4*256 + 20*$1 + 4*$1))
+}
+extended_table () {
+       echo $(($(ofs_table "$1") + 4*$1))
+}
+
+test_expect_success 'set up base packfile and variables' '
+       # the hash of this content starts with ff, which
+       # makes some later computations much simpler
+       echo 74 >file &&
+       git add file &&
+       git commit -m base &&
+       git repack -ad &&
+       base=$(echo .git/objects/pack/*) &&
+       chmod +w $base &&
+       mkdir base-backup &&
+       cp $base base-backup/ &&
+       object=$(git rev-parse HEAD:file)
+'
+
+test_expect_success 'pack/index object count mismatch' '
+       do_pack $object &&
+       munge $pack 8 "\377\0\0\0" &&
+       clear_base &&
+
+       # We enumerate the objects from the completely-fine
+       # .idx, but notice later that the .pack is bogus
+       # and fail to show any data.
+       echo "$object missing" >expect &&
+       git cat-file --batch-all-objects --batch-check >actual &&
+       test_cmp expect actual &&
+
+       # ...and here fail to load the object (without segfaulting),
+       # but fallback to a good copy if available.
+       test_must_fail git cat-file blob $object &&
+       restore_base &&
+       git cat-file blob $object >actual &&
+       test_cmp file actual &&
+
+       # ...and make sure that index-pack --verify, which has its
+       # own reading routines, does not segfault.
+       test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'matched bogus object count' '
+       do_pack $object &&
+       munge $pack 8 "\377\0\0\0" &&
+       munge $idx $((255 * 4)) "\377\0\0\0" &&
+       clear_base &&
+
+       # Unlike above, we should notice early that the .idx is totally
+       # bogus, and not even enumerate its contents.
+       >expect &&
+       git cat-file --batch-all-objects --batch-check >actual &&
+       test_cmp expect actual &&
+
+       # But as before, we can do the same object-access checks.
+       test_must_fail git cat-file blob $object &&
+       restore_base &&
+       git cat-file blob $object >actual &&
+       test_cmp file actual &&
+
+       test_must_fail git index-pack --verify $pack
+'
+
+# Note that we cannot check the fallback case for these
+# further .idx tests, as we notice the problem in functions
+# whose interface doesn't allow an error return (like use_pack()),
+# and thus we just die().
+#
+# There's also no point in doing enumeration tests, as
+# we are munging offsets here, which are about looking up
+# specific objects.
+
+test_expect_success 'bogus object offset (v1)' '
+       do_pack $object --index-version=1 &&
+       munge $idx $((4 * 256)) "\377\0\0\0" &&
+       clear_base &&
+       test_must_fail git cat-file blob $object &&
+       test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus object offset (v2, no msb)' '
+       do_pack $object --index-version=2 &&
+       munge $idx $(ofs_table 1) "\0\377\0\0" &&
+       clear_base &&
+       test_must_fail git cat-file blob $object &&
+       test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus offset into v2 extended table' '
+       do_pack $object --index-version=2 &&
+       munge $idx $(ofs_table 1) "\377\0\0\0" &&
+       clear_base &&
+       test_must_fail git cat-file blob $object &&
+       test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus offset inside v2 extended table' '
+       # We need two objects here, so we can plausibly require
+       # an extended table (if the first object were larger than 2^31).
+       do_pack "$object $(git rev-parse HEAD)" --index-version=2 &&
+
+       # We have to make extra room for the table, so we cannot
+       # just munge in place as usual.
+       {
+               dd if=$idx bs=1 count=$(($(ofs_table 2) + 4)) &&
+               printf "\200\0\0\0" &&
+               printf "\377\0\0\0\0\0\0\0" &&
+               dd if=$idx bs=1 skip=$(extended_table 2)
+       } >tmp &&
+       mv tmp "$idx" &&
+       clear_base &&
+       test_must_fail git cat-file blob $object &&
+       test_must_fail git index-pack --verify $pack
+'
+
+test_expect_success 'bogus OFS_DELTA in packfile' '
+       # Generate a pack with a delta in it.
+       base=$(test-genrandom foo 3000 | git hash-object --stdin -w) &&
+       delta=$(test-genrandom foo 2000 | git hash-object --stdin -w) &&
+       do_pack "$base $delta" --delta-base-offset &&
+       rm -f .git/objects/??/* &&
+
+       # Double check that we have the delta we expect.
+       echo $base >expect &&
+       echo $delta | git cat-file --batch-check="%(deltabase)" >actual &&
+       test_cmp expect actual &&
+
+       # Now corrupt it. We assume the varint size for the delta is small
+       # enough to fit in the first byte (which it should be, since it
+       # is a pure deletion from the base), and that original ofs_delta
+       # takes 2 bytes (which it should, as it should be ~3000).
+       ofs=$(git show-index <$idx | grep $delta | cut -d" " -f1) &&
+       munge $pack $(($ofs + 1)) "\177\377" &&
+       test_must_fail git cat-file blob $delta >/dev/null
+'
+
+test_done
index 0c10c856a96072a1b0c37530a9f5c8605d8833b5..38321d19efbee0da62a9327f5849521093fbe077 100755 (executable)
@@ -679,10 +679,12 @@ test_expect_success 'fetching with auto-gc does not lock up' '
        EOF
        git clone "file://$D" auto-gc &&
        test_commit test2 &&
-       cd auto-gc &&
-       git config gc.autoPackLimit 1 &&
-       GIT_ASK_YESNO="$D/askyesno" git fetch >fetch.out 2>&1 &&
-       ! grep "Should I try again" fetch.out
+       (
+               cd auto-gc &&
+               git config gc.autoPackLimit 1 &&
+               GIT_ASK_YESNO="$D/askyesno" git fetch >fetch.out 2>&1 &&
+               ! grep "Should I try again" fetch.out
+       )
 '
 
 test_done
index 7e8c40b97b4eecc2347ab2986a97b62148fe5f88..1b75c919651a8126e2a327f3d9645d4377823726 100755 (executable)
@@ -17,6 +17,12 @@ BEGIN
 use Cwd;
 use File::Basename;
 
+sub adjust_dirsep {
+       my $path = shift;
+       $path =~ s{\\}{/}g;
+       return $path;
+}
+
 BEGIN { use_ok('Git') }
 
 # set up
@@ -33,7 +39,7 @@ BEGIN
 is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent");
 ok($r->config_bool("test.booltrue"), "config_bool: true");
 ok(!$r->config_bool("test.boolfalse"), "config_bool: false");
-is($r->config_path("test.path") =~ s/\\/\//gr, $r->config("test.pathexpanded"),
+is(adjust_dirsep($r->config_path("test.path")), $r->config("test.pathexpanded"),
    "config_path: ~/foo expansion");
 is_deeply([$r->config_path("test.pathmulti")], ["foo", "bar"],
    "config_path: multiple values");
index fbe0a27ef3295fe3312fb72a478571bfb450cb25..30a64a98dc8b53a3a2d7edfaa57a8ee51d5d63e7 100644 (file)
@@ -41,7 +41,6 @@ static int no_job(struct child_process *cp,
 }
 
 static int task_finished(int result,
-                        struct child_process *cp,
                         struct strbuf *err,
                         void *pp_cb,
                         void *pp_task_cb)
index 94b387b499714911c9dfb6dd0940cb3f25a2397e..8e48a5c9909ec7e8ba44e5b0678455b4dc8d2d02 100644 (file)
--- a/trailer.c
+++ b/trailer.c
@@ -234,7 +234,7 @@ static const char *apply_command(const char *command, const char *arg)
        cp.use_shell = 1;
 
        if (capture_command(&cp, &buf, 1024)) {
-               error("running trailer command '%s' failed", cmd.buf);
+               error(_("running trailer command '%s' failed"), cmd.buf);
                strbuf_release(&buf);
                result = xstrdup("");
        } else {