summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2025-02-27gitlab-ci: fix "msvc-meson" test job succeeding despite test failuresPatrick Steinhardt1-1/+1
We have recently noticed that the "msvc-meson" test job in GitLab CI succeeds even if there are failures. This is somewhat puzzling because we use exactly the same command as we do on GitHub Actions, and there the jobs fail as exected. As it turns out, this is another weirdness of the GitLab CI hosted runner for Windows [1]: by default, even successful commands will not make the job fail. Interestingly though, this depends on what exactly the command is that you're running -- the MinGW-based job for example works alright and does fail as expected. The root cause here seems to be specific behaviour of PowerShell. The invocation of `ForEach-Object` does not bubble up any errors in case the invocation of `meson test` fails, and thus we don't notice the error. This is specific to executing the command in a loop: other build steps where we execute commands directly fail as expected. This is because the specific version of PowerShell that we use in the runner does not know about `PSNativeCommandUseErrorActionPreference` yet, which controls whether native commands like "meson.exe" honor the `ErrorActionPreference` variable. The preference has been introduced with PowerShell 7.3 and is default-enabled since PowerShell 7.4, but GitLab's hosted runners still seem to use PowerShell 5.1. Consequently, when tests fail, we won't bubble up the error at all from the loop and thus the job doesn't fail. This isn't an issue in other cases though where we execute native commands directly, as the GitLab runner knows to check the last error code after every command. The same thing doesn't seem to be an issue on GitHub Actions, most likely because it uses PowerShell 7.4. Curiously, the preference for `PSNativeCommandUseErrorActionPreference` is disabled there, but the jobs fail as expected regardless of that. It's puzzling, but I do not have enough PowerShell expertise to give a definitive answer as to why it works there. In any case, Meson 1.8 will likely get support for slicing tests [1], so we can eventually get rid of the whole PowerShell script. For now, work around the issue by explicitly exiting out of the loop with a non-zero error code if we see that Meson has failed. [1]: https://github.com/mesonbuild/meson/pull/14092 Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26gitlab-ci: restrict maximum number of link jobs on WindowsPatrick Steinhardt1-1/+1
The hosted Windows runners on GitLab.com only have 7.5GB of RAM. Given that "link.exe" provided by Microsoft Visual Studio is multi-threaded by itself already and thus quite memory hungry this can quickly lead to memory starvation, out-of-memory situations and thus failed CI jobs. Fix the issue by limiting the number of concurrent linker jobs. The same issue hasn't been observed on GitHub Actions yet, probably because it got more than twice the amount of RAM with 16GB. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: consistently use custom program paths to resolve programsPatrick Steinhardt1-6/+6
The calls to `find_program()` in our documentation don't use our custom program path. This variable gets populated on Windows with the location of Git for Windows so that we can use it to provide our build tools. Consequently, we may not be able to find all necessary binaries on Windows. Adapt the calls to use the program path to fix this. While at it, drop `required: true` arguments, which are the default anyway. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: fix overwritten `git` variablePatrick Steinhardt2-4/+3
We're assigning the `git` variable in three places: - In "meson.build" to store the external Git executable. - In "meson.build" to store the compiled Git executable. - In "Documentation/meson.build" to store the external Git executable, a second time. The last case is only needed because we overwrite the original variable with the built version. Rename the variable used for the built Git executable so that we don't have to resolve the external Git executable multiple times. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: prevent finding sed(1) in a loopPatrick Steinhardt2-2/+3
We're searching for the sed(1) executable in a loop, which will make us try to find it multiple times. Starting with the preceding commit we already declare a variable for that program in the top-level build file. Use it so that we only need to search for the program once. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: improve handling of `sane_tool_path` optionPatrick Steinhardt2-11/+10
The `sane_tool_path` option can be used to override the PATH variable from which the build process, tests and ultimately Git will end up picking programs from. It is currently lacking though because we only use it to populate the PATH environment variable for executed scripts and for the `BROKEN_PATH_FIX` mechanism, but we don't use it to find programs used in the build process itself. Fix this issue by treating it similar to the Windows-specific paths, which will make us use it both to find programs and to populate the PATH environment variable. To help with this fix, change the type of the option to be an array of paths, which makes the handling a bit easier for us. It's also the correct thing to do as the input indeed is a list of paths. Furthermore, the option now overrides the default behaviour on Windows, which si to pick up tools from Git for Windows. This is done so that it becomes easier to override that default behaviour in case it's not desired. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: improve PATH handlingPatrick Steinhardt1-7/+7
When locating programs required for the build we give some special treatment to Windows systems so that we know to also look up tools provided by a Git for Windows installation. This ensures that the build doesn't have any prerequisites other than Microsoft Visual Studio, Meson and Git for Windows. Consequently, some of the programs returned by `find_program()` may not be found via PATH, but via these extra directories. But while Meson can use these tools directly without any special treatment, any scripts that we execute may not be able to find those programs. To help them we thus prepend the directories of a subset of the found programs to PATH. This doesn't make much sense though: we don't need to prepend PATH for any program that was found via PATH, but we really only need to do so for programs located via the extraneous Windows-specific paths. So instead of prepending all programs paths, we really only need to prepend the Windows-specific paths. Adapt the code accordingly by only prepeding Windows-specific paths to PATH, which both simplifies the code and clarifies intent. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: drop separate version libraryPatrick Steinhardt1-16/+5
When building `libgit.a` we link it against a `libgit_version.a` library that contains the version information that we inject at build time. The intent of this is to avoid rebuilding all of `libgit.a` whenever the version changes. But that wouldn't happen in the first place, as we know to just rebuild the files that depend on the generated "version-def.h" file. This is an artifact of an earlier version of the Meson build infra that didn't ultimately land. We didn't yet have "version-def.h", and instead injected the version via preprocessor directives. And here we would have rebuilt all of `libgit.a` indeed in case the version changes, because the preprocessor directive applied to all files. Stop building the separate library and instead add "version-def.h" to the list of source files directly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: stop linking libcurl into all executablesPatrick Steinhardt1-2/+4
We set up libcurl via the `libgit_dependencies` variable, which gets propagated into every user of the `libgit` dependency. This is not necessary though, as most of our executables aren't even supposed to link against libcurl. Fix this by only propagating include directories as a libgit dependency and propagating the full curl dependency via `libgit_curl`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: introduce `libgit_curl` dependencyPatrick Steinhardt1-21/+18
We've got a set of common source files that we use for those executables that link against libcurl. The setup is somewhat repetitive though. Simplify it by declaring a `libgit_curl` dependency that bundles all of it together. Note that we don't include curl itself as a dependency. This is because we already pull it in transitively via the libgit dependency, which is unfortunate because libgit itself shouldn't actually link against curl in the first place. This will get fixed in the next commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: simplify use of the common-main libraryPatrick Steinhardt4-25/+24
The "common-main.c" file is used by multiple executables. In order to make it easy to set it up we have created a separate library that these executables can link against. All of these executables also want to link against `libgit.a` though, which makes it necessary to specify both of these as dependencies for every executable. Simplify this a bit by declaring the library as a source dependency: instead of creating a static library, we now instead compile the common set of files into each executable separately. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: inline the static 'git' libraryPatrick Steinhardt1-9/+7
When setting up `libgit.a` we first create the static library itself, and then declare it as part of a dependency such that compile arguments, include directories and transitive dependencies get propagated to the users of that library. As such, the static library isn't expected to be used by anything but the declared dependency. Inline the static library so that we don't even use a separate variable for it. This avoids any kind of confusion that may arise and clarifies how the library is supposed to be used. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: fix OpenSSL fallback when not explicitly requiredPatrick Steinhardt1-1/+6
When OpenSSL isn't provided by the system we know to fall back to the subproject wrapper. This is especially helpful on Windows systems, where you typically don't have OpenSSL available, in order to reduce the number of required dependencies. The fallback is broken though when the OpenSSL backend is set to 'auto' as we end up calling `dependency('openssl', required: false)` in that case, which implicitly disables falling back to the wrapper. Fix the issue by re-allowing the fallback in case either OpenSSL is required or in case the backend is set to 'auto'. While at it, fix reporting of the backend in case the user asked us to pick no HTTPS backend at all. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26meson: fix exec path with enabled runtime prefixPatrick Steinhardt1-1/+3
When the runtime prefix option is enabled, Git is built such that it knows to locate its binaries relative to the directory a binary is being executed from. This requires us to figure out relative paths, which is handled in `system_prefix()` by trying to strip a couple of well-known paths. One of these paths, GIT_EXEC_PATH, is expected to be absolute when runtime prefixes are enabled, but relative otherwise. And while our Makefile gets this correctly, in Meson we always wire up the absolute path, which may result in us not being able to find binaries. Fix this by conditionally injecting the paths depending on whether or not the `runtime_prefix` option is enabled. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26Git 2.49-rc0v2.49.0-rc0Junio C Hamano2-1/+7
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-26Merge branch 'jk/check-mailmap-wo-name-fix'Junio C Hamano2-1/+13
"git check-mailmap" segfault fix. * jk/check-mailmap-wo-name-fix: mailmap: fix check-mailmap with full mailmap line
2025-02-26Merge branch 'ek/mingw-rename-symlink'Junio C Hamano1-1/+3
Symlink renaming fix. * ek/mingw-rename-symlink: compat/mingw: rename the symlink, not the target
2025-02-25merge-strategies.adoc: detail submodule mergeLucas Seiki Oshiro1-0/+10
Submodule merges are, in general, similar to other merges based on oid three-way-merge. When a conflict happens, however, Git has two special cases (introduced in 68d03e4a6e44) on handling the conflict before yielding it to the user. From the merge-ort and merge-recursive sources: - "Case #1: a is contained in b or vice versa": both strategies try to perform a fast-forward in the submodules if the commit referred by the conflicted submodule is descendant of another; - "Case #2: There are one or more merges that contain a and b in the submodule. If there is only one, then present it as a suggestion to the user, but leave it marked unmerged so the user needs to confirm the resolution." Add a small paragraph on merge-strategies.adoc describing this behavior. Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Elijah Newren <newren@gmail.com> Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25BreakingChanges: clarify branches/ and remotes/Junio C Hamano1-2/+2
As we have created an empty .git/branches/ hierarchy until fairly recently, these directories may be found in modern repositories, but it is highly unlikely that they are being used. Reported-by: Jakub Wilk <jwilk@jwilk.net> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25The fourteenth batchJunio C Hamano1-0/+16
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25Merge branch 'po/meson-perl-fix'Junio C Hamano1-1/+16
Upgrade the minimum Perl version enforced by meson-based build to match what Makefile-based build uses. * po/meson-perl-fix: meson: fix Perl version check for Meson versions before 1.7.0 meson: bump minimum required Perl version to 5.26.0
2025-02-25Merge branch 'ms/rename-match-name-with-pattern'Junio C Hamano3-24/+25
Code renaming. * ms/rename-match-name-with-pattern: refspec: clarify function naming and documentation
2025-02-25Merge branch 'ad/set-default-target-in-makefiles'Junio C Hamano15-11/+46
Correct the default target in Documentation/Makefile, and future-proof all Makefiles from similar breakages by declaring the default target (which happens to be "all") upfront. * ad/set-default-target-in-makefiles: Makefile: set default goals in makefiles
2025-02-25Merge branch 'pw/merge-tree-stdin-deadlock-fix'Junio C Hamano2-9/+13
"git merge-tree --stdin" has been improved (including a workaround for a deadlock). * pw/merge-tree-stdin-deadlock-fix: merge-tree: fix link formatting in html docs merge-tree: improve docs for --stdin merge-tree: only use basic merge config merge-tree: remove redundant code merge-tree --stdin: flush stdout to avoid deadlock
2025-02-25Merge branch 'mh/doc-commit-title-not-subject'Junio C Hamano2-8/+8
The documentation of "git commit" and "git rebase" now refer to commit titles as such, not "subject". * mh/doc-commit-title-not-subject: doc: use 'title' consistently
2025-02-25Merge branch 'bc/diff-reject-empty-arg-to-pickaxe'Junio C Hamano2-0/+20
The -G/-S options to the "diff" family of commands caused us to hit a BUG() when they get no values; they have been corrected. * bc/diff-reject-empty-arg-to-pickaxe: diff: don't crash with empty argument to -G or -S
2025-02-25Merge branch 'tb/new-make-fix'Junio C Hamano1-4/+4
Workaround the overly picky HT/SP rule in newer GNU Make. * tb/new-make-fix: Makefile: remove accidental recipe prefix in conditional
2025-02-25Merge branch 'da/xdiff-w-sign-compare-workaround'Junio C Hamano6-12/+10
Noises from "-Wsign-compare" in the borrowed xdiff code has been squelched. * da/xdiff-w-sign-compare-workaround: xdiff: avoid signed vs. unsigned comparisons in xutils.c xdiff: avoid signed vs. unsigned comparisons in xpatience.c xdiff: avoid signed vs. unsigned comparisons in xhistogram.c xdiff: avoid signed vs. unsigned comparisons in xemit.c xdiff: avoid signed vs. unsigned comparisons in xdiffi.c xdiff: move sign comparison warning guard into each file
2025-02-25t/unit-tests: convert oidtree test to use clar test frameworkSeyi Kuforiji4-124/+109
Adapt oidtree test script to clar framework by using clar assertions where necessary. `cl_parse_any_oid()` ensures the hash algorithm is set before parsing. This prevents issues from an uninitialized or invalid hash algorithm. Introduce 'test_oidtree__initialize` handles the to set up of the global oidtree variable and `test_oidtree__cleanup` frees the oidtree when all tests are completed. With this change, `check_each` stops at the first error encountered, making it easier to address it. Mentored-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Seyi Kuforiji <kuforiji98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25t/unit-tests: convert oidmap test to use clar test frameworkSeyi Kuforiji4-183/+138
Adapt oidmap test script to clar framework by using clar assertions where necessary. `cl_parse_any_oid()` ensures the hash algorithm is set before parsing. This prevents issues from an uninitialized or invalid hash algorithm. Introduce 'test_oidmap__initialize` handles the to set up of the global oidmap map with predefined key-value pairs, and `test_oidmap__cleanup` frees the oidmap and its entries when all tests are completed. The test loops through all entries to detect multiple errors. With this change, it stops at the first error encountered, making it easier to address it. Mentored-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Seyi Kuforiji <kuforiji98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25t/unit-tests: convert oid-array test to use clar test frameworkSeyi Kuforiji4-128/+131
Adapt oid-array test script to clar framework by using clar assertions where necessary. Remove descriptions from macros to reduce redundancy, and move test input arrays to global scope for reuse across multiple test functions. Introduce `test_oid_array__initialize()` to explicitly initialize the hash algorithm. These changes streamline the test suite, making individual tests self-contained and reducing redundant code. Mentored-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Seyi Kuforiji <kuforiji98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25t/unit-tests: implement clar specific oid helper functionsSeyi Kuforiji5-26/+21
`get_oid_arbitrary_hex()` and `init_hash_algo()` are both required for oid-related tests to run without errors. In the current implementation, both functions are defined and declared in the `t/unit-tests/lib-oid.{c,h}` which is utilized by oid-related tests in the homegrown unit tests structure. Adapt functions in lib-oid.{c,h} to use clar. Both these functions become available for oid-related test files implemented using the clar testing framework, which requires them. This will be used by subsequent commits. Mentored-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Seyi Kuforiji <kuforiji98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_rest(): rewrite return handling for clarityJeff King1-6/+6
We have a pattern like: if (error1) ...handle error 1... else if (error2) ...handle error 2... else ...return buf... ...free buf and return NULL... This is a little subtle because it is the return in the success block that lets us skip the common error handling. Rewrite this instead to free the buffer in each error path, marking it as NULL, and then all code paths can use the common return. This should make the logic a bit easier to follow. It does mean duplicating the buf cleanup for errors, but it's a single line. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_rest(): simplify error handlingJeff King1-3/+3
Inflating a loose object is considered successful only if we got Z_STREAM_END and there were no more bytes. We check both of those conditions and return success, but then have to check them a second time to decide which error message to produce. I.e., we do something like this: if (!error_1 && !error_2) ...return success... if (error_1) ...handle error1... else if (error_2) ...handle error2... ...common error handling... This repetition was the source of a small bug fixed in an earlier commit (our Z_STREAM_END check was not the same in the two conditionals). Instead we can chain them all into a single if/else cascade, which avoids repeating ourselves: if (error_1) ...handle error1... else if (error_2) ...handle error2.... else ...return success... ...common error handling... Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_rest(): never clean up zstreamJeff King1-10/+8
The unpack_loose_rest() function has funny ownership semantics: we pass in a z_stream opened by the caller, but then only _sometimes_ close it. This oddity has developed over time. When the function was originally split out in 5180cacc20 (Split up unpack_sha1_file() some more, 2005-06-02), it always called inflateEnd() to clean up the stream (though nowadays it is a git_zstream and we call git_inflate_end()). But in 7efbff7531 (unpack_sha1_file(): detect corrupt loose object files., 2007-03-05) we added error code paths which don't close the stream. This makes some sense, as we'd still look at parts of the stream struct to decide which error to show (though I am not sure in practice if inflateEnd() even touches those fields). This subtlety makes it hard to know when the caller has to clean up the stream and when it does not. That led to the leak fixed by aa9ef614dc (object-file: fix memory leak when reading corrupted headers, 2024-08-14). Let's instead always leave the stream intact, forcing the caller to clean it up. You might think that would create more work for the callers, but it actually ends up simplifying them, since they can put the call to git_inflate_end() in the common cleanup code path. Two things to note, though: - The check_stream_oid() function is used as a replacement for unpack_loose_rest() in read_loose_object() to read blobs. It inherited the same funny semantics, and we should fix it here, too (to keep the cleanup in read_loose_object() consistent). - In read_loose_object() we need a second "out" label, as we can jump to the existing label before opening the stream at all (and since the struct is opaque, there is no way to if it was initialized or not, so we must not call git_inflate_end() in that case). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_rest(): avoid numeric comparison of zlib statusJeff King1-1/+1
When unpacking the actual content of a loose object file, we insist both that the status code we got is Z_STREAM_END, and that we consumed all bytes. If we didn't, we'll return an error, but the specific error message we produce depends on which of the two error conditions we saw. So we'll check both a second time to decide which error to produce. But this second time, our status code check is loose: it checks for a negative status value. This can get confused by zlib codes which are not negative, such as Z_NEED_DICT. In this case we'd erroneously print nothing at all, when we should say "corrupt loose object". Instead, this second check should check explicitly against Z_STREAM_END. Note that Z_OK is "0", so the existing code also produced no message for Z_OK. But it's impossible to see that status, since we only break out of the inflate loop when we stop seeing Z_OK (so a stream which has more bytes than its object header claims would eventually yield Z_BUF_ERROR). There's no test here, as it would require a loose object whose zlib stream returns Z_NEED_DICT in the middle of the object content. I think that is probably possible, but even our Z_NEED_DICT test in t1006 does not trigger this, because we hit that error while reading the header. I found this bug while reviewing all callers of git_inflate() for bugs similar to the one we saw in unpack_loose_header(). This was the only other case that did a numeric comparison rather than explicitly checking for Z_STREAM_END. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_header(): avoid numeric comparison of zlib statusJeff King2-1/+3
When unpacking a loose header, we try to inflate the first 32 bytes. We'd expect either Z_OK (we filled up the output buffer, but there are more bytes in the object) or Z_STREAM_END (this is a tiny object whose header and content fit in the buffer). We check for that with "if (status < Z_OK)", making the assumption that all of the errors we'd see have negative values (as Z_OK itself is "0", and Z_STREAM_END is "1"). But there's at least one case this misses: Z_NEED_DICT is "2". This isn't something we'd ever expect to see, but if we do see it, we should consider it an error (since we have no dictionary to load). Instead, the current code interprets Z_NEED_DICT as success and looks for the object header's terminating NUL in the bytes we've read. This will generaly be zero bytes if the dictionary is mentioned at the start of the stream. So we'll fail to find it and complain "the header is too long" (ULHR_LONG). But really, the problem is that the object is malformed, and we should return ULHR_BAD. This is a minor bug, as we consider both cases to be an error. But it does mean we print the wrong error message. The test case added in the previous patch triggers this code, so we can just confirm the error message we see here. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25git_inflate(): skip zlib_post_call() sanity check on Z_NEED_DICTJeff King2-11/+48
This fixes a case where malformed object input can cause us to hit a BUG() call in the git-zlib.c code. The zlib format allows the use of preset dictionaries to reduce the size of deflated data. The checksum of the dictionary is computed by the deflate code and goes into the stream. On the inflating side, zlib sees the dictionary checksum and returns Z_NEED_DICT, asking the caller to provide the dictionary data via inflateSetDictionary(). This should never happen in Git, because we never provide a dictionary for deflating (and if we get a stream that mentions a dictionary, we have no idea how to provide it). So normally Z_NEED_DICT is a hard error for us. But something interesting happens if we _do_ happen to see it (e.g., because of a corrupt or malicious input). In git_inflate() as we loop over calls to zlib's inflate(), we translate between our large-integer git_zstream values and zlib's native z_stream types, copying in and out with zlib_pre_call() and zlib_post_call(). In zlib_post_call() we have a few sanity checks, including one that checks that the number of bytes consumed by zlib (as measured by it moving the "next_in" pointer) is equal to the movement of its "total_in" count. But these do not correspond when we see Z_NEED_DICT! Zlib consumes the bytes from the input buffer but it does not increment total_in. And so we hit the BUG("total_in mismatch") call. There are a few options here: - We could ditch that BUG() check. It is making too many assumptions about how zlib updates these values. But it does have value in most cases as a sanity check on the values we're copying. - We could skip the zlib_post_call() entirely when we see Z_NEED_DICT. We know that it's hard error for us, so we should just send the status up the stack and let the caller bail. The downside is that if we ever did want to support dictionaries, we couldn't (the git_zstream will be out of sync, since we never copied its values back from the z_stream). - We could continue to call zlib_post_call(), but skip just that BUG() check if the status is Z_NEED_DICT. This keeps git_inflate() as a thin wrapper around inflate(), and would let us later support dictionaries for some calls if we wanted to. This patch uses the third approach. It seems like the least-surprising thing to keep git_inflate() a close to inflate() as possible. And while it makes the diff a bit larger (since we have to pass the status down to to the zlib_post_call() function), it's a static local function, and every caller by definition will have just made a zlib call (and so will have a status integer). Co-authored-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_header(): fix infinite loop on broken zlib inputJeff King2-1/+20
When reading a loose object, we first try to expand the first 32 bytes to read the type+size header. This is enough for any of the normal Git types. But since 46f034483e (sha1_file: support reading from a loose object of unknown type, 2015-05-03), the caller can also ask us to parse any unknown names, which can be much longer. In this case we keep inflating until we find the NUL at the end of the header, or hit Z_STREAM_END. But what if zlib can't make forward progress? For example, if the loose object file is truncated, we'll have no more data to feed it. It will return Z_BUF_ERROR, and we'll just loop infinitely, calling git_inflate() over and over but never seeing new bytes nor an end-of-stream marker. We can fix this by only looping when we think we can make forward progress. This will always be Z_OK in this case. In other code we might also be able to continue on Z_BUF_ERROR, but: - We will never see Z_BUF_ERROR because the output buffer is full; we always feed a fresh 32-byte buffer on each call to git_inflate(). - We may see Z_BUF_ERROR if we run out of input. But since we've fed the whole mmap'd buffer to zlib, if it runs out of input there is nothing more we can do. So if we don't see Z_OK (and didn't see the end-of-header NUL, otherwise we'd have broken out of the loop), then we should stop looping and return an error. The test case shows an example where the input is truncated (which gives us the input Z_BUF_ERROR case above). Although we do operate on objects we might get from an untrusted remote, I don't think the security implications of this bug are too great. It can only trigger if both of these are true: - You're reading a loose object whose on-disk representation was written by an attacker. So fetching an object (or receiving a push) are mostly OK, because even with unpack-objects it is our local, trusted code that writes out the object file. The exception may be fetching from an untrusted local repo, or using dumb-http, which copies objects verbatim. But... - The only code path which triggers the inflate loop is cat-file's --allow-unknown-type option. This is unlikely to be called at all outside of debugging. But I also suspect that objects with non-standard types (or that are truncated) would not survive the usual fetch/receive checks in the first place. So I think it would be quite hard to trick somebody into running the infinite loop, and we can just fix the bug. Co-authored-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_header(): report headers without NUL as "bad"Jeff King1-1/+1
If a caller asks us to read the whole loose object header value into a strbuf (e.g., via "cat-file --allow-unknown-type"), we'll keep reading until we see a NUL byte marking the end of the header. If we hit Z_STREAM_END before seeing the NUL, we obviously have to stop. But we return ULHR_TOO_LONG, which doesn't make any sense. The "too long" return code is used in the normal, 32-byte limited mode to indicate that we stopped looking. There is no such thing as "too long" here, as we'd keep reading forever until we see the end of stream or the NUL. Instead, we should return ULHR_BAD. The loose object has no NUL marking the end of header, so it is malformed. The behavior difference is slight; in either case we'd consider the object unreadable and refuse to go further. The only difference is the specific error message we produce. There's no test case here, as we'd need to generate a valid zlib stream without a NUL. That's not something Git will do without writing new custom code. And in the next patch we'll fix another bug in this area which will make this easier to do (and we will test it then). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25unpack_loose_header(): simplify next_out assignmentJeff King1-4/+3
When using OBJECT_INFO_ALLOW_UNKNOWN_TYPE to unpack a header that doesn't fit into our initial 32-byte buffer, we loop over calls git_inflate(), feeding it our buffer to the "next_out" pointer each time. As the code is written, we reset next_out after each inflate call (and after reading the output), ready for the next loop. This isn't wrong, but there are a few advantages to setting up "next_out" right before each inflate call, rather than after: 1. It drops a few duplicated lines of code. 2. It makes it obvious that we always feed a fresh buffer on each call (and thus can never see Z_BUF_ERROR due to due to a lack of output space). 3. After we exit the loop, we'll leave stream->next_out pointing to the end of the fetched data (this is how zlib callers find out how much data is in the buffer). This doesn't matter in practice, since nobody looks at it again. But it's probably the least-surprising thing to do, as it matches how next_out is left when the whole thing fits in the initial 32-byte buffer (and we don't enter the loop at all). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-25loose_object_info(): BUG() on inflating content with unknown typeJeff King1-0/+2
After unpack_loose_header() returns, it will have inflated not only the object header, but possibly some bytes of the object content. When we call unpack_loose_rest() to extract the actual content, it finds those extra bytes by skipping past the header's terminating NUL in the buffer. Like this: int bytes = strlen(buffer) + 1; n = stream->total_out - bytes; ... memcpy(buf, (char *) buffer + bytes, n); This won't work with the OBJECT_INFO_ALLOW_UNKNOWN_TYPE flag, as there we allow a header of arbitrary size. We put into a strbuf, but feed only the final 32-byte chunk we read to unpack_loose_rest(). In that case stream->total_out may unexpectedly large, and thus our "n" will be large, causing an out-of-bounds read (we do check it against our allocated buffer size, which prevents an out-of-bounds write). Probably this could be made to work by feeding the strbuf to unpack_loose_rest(), along with adjusting some types (e.g., "bytes" would need to be a size_t, since it is no longer operating on a 32-byte buffer). But I don't think it's possible to actually trigger this in practice. The only caller who passes ALLOW_UNKNOWN_TYPE is cat-file, which only allows it with the "-t" and "-s" options (neither of which access the content). There is one way you can _almost_ trigger it: the oid compat routines (i.e., accessing sha1 via sha256 names and vice versa) will convert objects on the fly (which requires access to the content) using the same flags that were passed in. So in theory this: t='some very large type field that causes an extra inflate call' sha1_oid=$(git hash-object -w -t "$t" file) sha256_oid=$(git rev-parse --output-object-format=sha256 $sha1_oid) git cat-file --allow-unknown-type -s $sha256_oid would try to access the content. But it doesn't work, because using compat objects requires an entry in the .git/objects/loose-object-idx file, and we don't generate such an entry for non-standard types (see the "compat" section of write_object_file_literally()). If we use "t=blob" instead, then it does access the compat object, but it doesn't trigger the problem (because "blob" is a standard short type name, and it fits in the initial 32-byte buffer). So given that this is almost a memory error bug, I think it's worth addressing. But because we can't actually trigger the situation, I'm hesitant to try a fix that we can't run. Instead let's document the restriction and protect ourselves from the out-of-bounds read by adding a BUG() check. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-24t/aggregate-results: fix paste(1) invocationD. Ben Knoble1-1/+1
When running `make test`, when missing prereqs the following is emitted: make aggregate-results usage: paste [-s] [-d delimiters] file ... fixed 1 success 30066 failed 0 broken 218 total 31274 POSIX says that `paste` requires a file operand; stdin was clearly intended by 49da404070 (test-lib: show missing prereq summary, 2021-11-20). Use it. Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-24commit: avoid parent list buildup in clear_commit_marks_many()René Scharfe1-4/+4
clear_commit_marks_1() clears the marks of the first parent and its first parent and so on, and saves the higher numbered parents in a list for later. There is no benefit in keeping that list growing with each handled commit. Clear it after each run to reduce peak memory usage. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-24http: allow using netrc for WebDAV-based HTTP protocolbrian m. carlson2-2/+11
For an extended period of time, we've enabled libcurl's netrc functionality, which will read credentials from the netrc file if none are provided. Unfortunately, we have also not documented this fact or written any tests for it, but people have come to rely on it. In 610cbc1dfb ("http: allow authenticating proactively", 2024-07-10), we accidentally broke the ability of users to use the netrc file for the WebDAV-based HTTP protocol. Notably, it works on the initial request but does not work on subsequent requests, which causes failures because that version of the protocol will necessarily make multiple requests. This happens because curl_empty_auth_enabled never returns -1, only 0 or 1, and so if http.proactiveAuth is not enabled, the username and password are always set to empty credentials, which prevents libcurl's fallback to netrc from working. However, in other cases, the server continues to get a 401 response and the credential helper is invoked, which is the normal behavior, so this was not noticed earlier. To fix this, change the condition to check for enabling empty auth and also not having proactive auth enabled, which should result in the username and password not being set to a single colon in the typical case, and thus the netrc file being used. Reported-by: Peter Georg <peter.georg@physik.uni-regensburg.de> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-21mailmap: fix check-mailmap with full mailmap lineJacob Keller2-1/+13
I recently had reported to me a crash from a coworker using the recently added sendemail mailmap support: 3724814 Segmentation fault (core dumped) git check-mailmap "bugs@company.xx" This appears to happen because of the NULL pointer name passed into map_user(). Fix this by passing "" instead of NULL so that we have a valid pointer. Signed-off-by: Jacob Keller <jacob.keller@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-21The thirteenth batchJunio C Hamano1-0/+5
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-21Merge branch 'ac/doc-http-ssl-type-config'Junio C Hamano1-0/+15
Two configuration variables about SSL authentication material that weren't mentioned in the documentations are now mentioned. * ac/doc-http-ssl-type-config: docs: indicate http.sslCertType and sslKeyType
2025-02-21Merge branch 'en/doc-renormalize'Junio C Hamano3-4/+5
Doc updates. * en/doc-renormalize: doc: clarify the intent of the renormalize option in the merge machinery
2025-02-21Merge branch 'jc/doc-boolean-synonyms'Junio C Hamano3-7/+10
Doc updates. * jc/doc-boolean-synonyms: doc: centrally document various ways tospell `true` and `false`