-
Notifications
You must be signed in to change notification settings - Fork 25.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start compiling with -Wsign-compare
#1840
base: master
Are you sure you want to change the base?
Conversation
There are issues in commit 5bd21fc: |
d15ab1d
to
0fa43fa
Compare
There are issues in commit 83ae1ed: |
Hi, when compiling with DEVELOPER=YesPlease, we explicitly disable the "-Wsign-compare" warning. This is mostly because our code base is full of cases where we don't bother at all whether something should be signed or unsigned, and enabling the warning would thus cause tons of warnings to pop up. Unfortunately, disabling this warning also masks real issues. There have been multiple CVEs in the Git project that would have been flagged by this warning (e.g. CVE-2022-39260, CVE-2022-41903 and several fixes in the vicinity of these CVEs). Furthermore, the final audit report by X41 D-Sec, who are the ones who have discovered some of the CVEs, hinted that it might be a good idea to become more strict in this context. Now simply enabling the warning globally does not fly due to the stated reason above that we simply have too many sites where we use the wrong integer types. Instead, this patch series introduces a new macro that allows us to explicitly mark files that generate such warnings. Like this, we can adapt the codebase over time and hopefully make this class of vulnerabilities harder to land. Changes in v2: - Explode the 6th patch into multiple patches with more careful analysis and refactorings - Drop the conversion of "gettext.c". To do it properly we'd have to fix the return type of `utf8_strwidth()`, which we have already marked as a todo. - Link to v1: https://lore.kernel.org/r/20241129-pks-sign-compare-v1-0-fc406b984bc9@pks.im Changes in v3: - Include Junio's fix for 32 bit platforms. - Improve a commit message. - Link to v2: https://lore.kernel.org/r/20241202-pks-sign-compare-v2-0-e7f0ad92a749@pks.im Changes in v4: - Rebased on top of e66fd72 (The fourteenth batch, 2024-12-06) to fix a couple of new errors in "git.c"' - Remove needless cast in "csum-file.c". - Refactor "pkt-line.c" to be safer regarding integer conversions. - Link to v3: https://lore.kernel.org/r/20241205-pks-sign-compare-v3-0-e211ee089717@pks.im There are a couple of trivial conflicts with kn/midx-wo-the-repository, but I don't think it makes sense to make that a dependency of this series. Let me know in case you disagree and I'll change the base of this series. Thanks! Patrick To: git@vger.kernel.org Cc: shejialuo <shejialuo@gmail.com> Cc: Jeff King <peff@peff.net> Cc: Junio C Hamano <gitster@pobox.com> --- b4-submit-tracking --- # This section is used internally by b4 prep for tracking purposes. { "series": { "revision": 4, "change-id": "20241128-pks-sign-compare-9cf7412bce1a", "prefixes": [], "history": { "v1": [ "20241129-pks-sign-compare-v1-0-fc406b984bc9@pks.im" ], "v2": [ "20241202-pks-sign-compare-v2-0-e7f0ad92a749@pks.im" ], "v3": [ "20241205-pks-sign-compare-v3-0-e211ee089717@pks.im" ] } } }
When compiling with DEVELOPER=YesPlease, we explicitly disable the "-Wsign-compare" warning. This is mostly because our code base is full of cases where we don't bother at all whether something should be signed or unsigned, and enabling the warning would thus cause tons of warnings to pop up. Unfortunately, disabling this warning also masks real issues. There have been multiple CVEs in the Git project that would have been flagged by this warning (e.g. CVE-2022-39260, CVE-2022-41903 and several fixes in the vicinity of these CVEs). Furthermore, the final audit report by X41 D-Sec, who are the ones who have discovered some of the CVEs, hinted that it might be a good idea to become more strict in this context. Now simply enabling the warning globally does not fly due to the stated reason above that we simply have too many sites where we use the wrong integer types. Instead, introduce a new set of macros that allow us to mark a file as being free of warnings with "-Wsign-compare". The mechanism is similar to what we do with `USE_THE_REPOSITORY_VARIABLE`: every file that is not marked with `DISABLE_SIGN_COMPARE_WARNINGS` will be compiled with those warnings enabled. These new markings will be wired up in the subsequent commits. Signed-off-by: Patrick Steinhardt <ps@pks.im>
Explicitly ignore "-Wsign-compare" warnings in our bundled copy of the regcomp implementation. We don't use the macro introduced in the preceding commit because this code does not include "git-compat-util.h" in the first place. Note that we already directly use "#pragma GCC diagnostic ignored" in "regcomp.c", so it shouldn't be an issue to use it directly in the new spot, either. Signed-off-by: Patrick Steinhardt <ps@pks.im>
GCC generates a warning in "headless.c" because we compare `slash` with `size`, where the former is an `int` and the latter is a `size_t`. Fix the warning by storing `slash` as a `size_t`, as well. This commit is being singled out because the file does not include the "git-compat-util.h" header, and consequently, we cannot easily mark it with the `DISABLE_SIGN_COMPARE_WARNING` macro. Signed-off-by: Patrick Steinhardt <ps@pks.im>
Mark code units that generate warnings with `-Wsign-compare`. This allows for a structured approach to get rid of all such warnings over time in a way that can be easily measured. Signed-off-by: Patrick Steinhardt <ps@pks.im>
There is no need anymore to disable `-Wsign-compare` now that all files that cause warnings have been marked accordingly. Drop the option. Signed-off-by: Patrick Steinhardt <ps@pks.im>
The `struct diff_flags` structure is essentially an array of flags, all of which have the same type. We can thus use `sizeof()` to iterate through all of the flags, which we do in `diff_flags_or()`. But while the statement returns an unsigned integer, we used a signed integer to iterate through the flags, which generates a warning. Fix this by using `size_t` for the index instead. Signed-off-by: Patrick Steinhardt <ps@pks.im>
On 32-bit platforms, ssize_t may be "int" while size_t may be "unsigned int". At times we compare the number of bytes we read stored in a ssize_t variable with "unsigned int", but that is done after we check that we did not get an error return (which is negative---and that is the whole reason why we used ssize_t and not size_t), so these comparisons are safe. But compilers may not realize that. Cast these to size_t to work around the false positives. On platforms with size_t/ssize_t wider than a normal int, this won't be an issue. Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Patrick Steinhardt <ps@pks.im>
Similar to the preceding commit, we get a warning in `get_packet_data()` on 32 bit platforms due to our lenient use of `ssize_t`. This function is kind of curious though: we accept an `unsigned size` of bytes to read, then store the actual number of bytes read in an `ssize_t` and return it as an `int`. This is a whole lot of integer conversions, and in theory these can cause us to overflow when the passed-in size is larger than `ssize_t`, which on 32 bit platforms is implemented as an `int`. None of the callers of that function even care about the number of bytes we have read, so returning that number is moot anyway. Refactor the function such that it only returns an error code, which plugs the potential overflow. While at it, convert the passed-in size parameter to be of type `size_t`. Signed-off-by: Patrick Steinhardt <ps@pks.im>
We have a bunch of loops which iterate up to an unsigned boundary using a signed index, which generates warnigs because we compare a signed and unsigned value in the loop condition. Address these sites for trivial cases and enable `-Wsign-compare` warnings for these code units. This patch only adapts those code units where we can drop the `DISABLE_SIGN_COMPARE_WARNINGS` macro in the same step. Signed-off-by: Patrick Steinhardt <ps@pks.im>
We have several loops in "daemon.c" that use a signed integer to loop through a `size_t`. Adapt them to instead use a `size_t` as counter value. Signed-off-by: Patrick Steinhardt <ps@pks.im>
The `max_connections` type tracks how many children git-daemon(1) would spawn at the same time. This value can be controlled via a command line switch: if given a positive value we'll set that up as the limit. But when given either zero or a negative value we don't enforce any limit at all. But even when being passed a negative value we won't actually store it, but normalize it to 0. Still, the variable used to store the config is using a signed integer, which causes warnings when comparing the number of accepted connections (`max_connections`) with the number of current connections being handled (`live_children`). Adapt the type of `max_connections` such that the types of both variables match. Signed-off-by: Patrick Steinhardt <ps@pks.im>
There are a couple of -Wsign-comparison warnings in "gpg-interface.c". Most of them are trivial and simply using signed integers to loop towards an upper unsigned bound. But in `parse_signed_buffer()` we have one case where the different signedness of the two values of a ternary expression results in a warning. Given that: - `size` will always be bigger than `len` due to the loop condition. - `eol` will always be after `buf + len` because it is found via memchr(3p) starting from `buf + len`. We know that both values will always be natural integers. Squelch the warning by casting the left-hand side to `size_t`. Signed-off-by: Patrick Steinhardt <ps@pks.im>
The `length` variable is used to store how many bytes we wish to emit from an object ID. This value will either be the full hash algorithm's length, or the abbreviated hash that can be set via `--abbrev` or the "core.abbrev" option. The former is of type `size_t`, whereas the latter is of type `int`, which causes a warning with "-Wsign-compare". The reason why `abbrev` is using a signed type is mostly that it is initialized with `-1` to indicate that we have to compute the minimum abbreviation length. This length is computed via `find_alignment()`, which always gets called before `emit_other()`, and thus we can assume that the value would never be negative in `emit_other()`. In fact, we can even assume that the value will always be at least `MINIMUM_ABBREV`, which is enforced by both `git_default_core_config()` and `parse_opt_abbrev_cb()`. We implicitly rely on this by subtracting up to 3 without checking for whether the value becomes negative. We then pass the value to printf(3p) to print the prefix of our object's ID, so if that assumption was violated we may end up with undefined behaviour. Squelch the warning by asserting this invariant and casting the value of `abbrev` to `size_t`. This allows us to store the whole length as an unsigned integer, which we can then pass to `fwrite()`. Signed-off-by: Patrick Steinhardt <ps@pks.im>
In `get_one_patchid()` we assign either the result of `strlen()` or `remove_space()` to `len`. But while the former correctly returns a `size_t`, the latter returns an `int` to indicate the length of the stripped string even though it cannot ever return a negative value. This causes a warning with "-Wsign-conversion". In fact, even `get_one_patchid()` itself is also using an integer as return value even though it always returns the length of the patch, and this bubbles up to other callers. Adapt the function and its helpers to use `size_t` for string lengths consistently. Signed-off-by: Patrick Steinhardt <ps@pks.im>
There are two -Wsign-compare warnings in "scalar.c", both of which are trivial: - We mistakenly use a signed integer to loop towards an upper unsigned bound in `cmd_reconfigure()`. - We subtract `path_sep - enlistment->buf`, which results in a signed integer, and use the value in a ternary expression where second value is unsigned. But as `path_sep` is being assigned the result of `find_last_dir_sep(enlistment->buf + offset)` we know that it must always be bigger than or equal to `enlistment->buf`, and thus the result will be positive. Address both of these warnings. Signed-off-by: Patrick Steinhardt <ps@pks.im>
In our test helpers we have two cases where we assign -1 to an `unsigned long`. The intent is to essentially mean "unbounded output", which is achieved via implicit wraparound of the value. This pattern causes warnings with -Wsign-compare though. Adapt it and instead use `ULONG_MAX` explicitly. Signed-off-by: Patrick Steinhardt <ps@pks.im>
0fa43fa
to
3aa04ed
Compare
There are issues in commit 441cf02: |
3aa04ed
to
aac9938
Compare
There are issues in commit f1f5978: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
留下評論
This PR exists merely to check compatibility with GitHub CI jobs.