Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

pks-t
Copy link
Member

@pks-t pks-t commented Oct 18, 2018

This PR removes all usages of git__strtol32 and git__strtol64. While these functions are fine to use when the string is known to be sanitized, many functions were using them with untrusted input that may not have been NUL-terminated. To avoid future misuse, let's get rid of them altogether in favor of git__strntol32 and git__strntol64.

pks-t added 10 commits October 18, 2018 11:25
When quick-parsing a commit, we use `git__strtol64` to parse the
commit's time. The buffer that's passed to `commit_quick_parse` is the
raw data of an ODB object, though, whose data may not be properly
formatted and also does not have to be `NUL` terminated. This may lead
to out-of-bound reads.

Use `git__strntol64` to avoid this problem.
We use `git__strtol64` to parse file modes of the index entries, which
does not limit the parsed buffer length. As the index can be essentially
treated as "untrusted" in that the data stems from the file system, it
may be misformatted and may not contain terminating `NUL` bytes. This
may lead to out-of-bounds reads when trying to parse index entries with
such malformatted modes.

Fix the issue by using `git__strntol64` instead.
We use `git__strtol64` and `git__strtol32` to parse the trailing commit
or author date and timezone of signatures. As signatures are usually
part of a commit or tag object and thus essentially untrusted data, the
buffer may be misformatted and may not be `NUL` terminated. This may
lead to an out-of-bounds read.

Fix the issue by using `git__strntol64` and `git__strntol32` instead.
When parsing integers from configuration values, we use `git__strtol64`.
This is fine to do, as we always sanitize values and can thus be sure
that they'll have a terminating `NUL` byte. But as this is the last
call-site of `git__strtol64`, let's just pass in the length explicitly
by calling `strlen` on the value to be able to remove `git__strtol64`
altogether.
The function `git__strtol64` does not take a maximum buffer length as
parameter. This has led to some unsafe usages of this function, and as
such we may consider it as being unsafe to use. As we have now
eradicated all usages of this function, let's remove it completely to
avoid future misuse.
We use the `git__strtol32` function to parse the child and entry count
of treecaches from the index, which do not accept a buffer length. As
the buffer that is being passed in is untrusted data and may thus be
malformed and may not contain a terminating `NUL` byte, we can overrun
the buffer and thus perform an out-of-bounds read.

Fix the issue by uzing `git__strntol32` instead.
Replace remaining uses of the `git__strtol32` function. While these uses
are all safe as the strings were either sanitized or from a trusted
source, we want to remove `git__strtol32` altogether to avoid future
misuse.
The function `git__strtol32` can easily be misused when untrusted data
is passed to it that may not have been sanitized with trailing `NUL`
bytes. As all usages of this function have now been removed, we can
remove this function altogether to avoid future misuse of it.
Some edge cases were currently completely untested, e.g. parsing numbers
greater than INT64_{MIN,MAX}, truncating buffers by length and invalid
characters. Add tests to verify that the system under test performs as
expected.
While `git__strntol64` tries to detect integer overflows when doing the
necessary arithmetics to come up with the final result, it does the
detection only after the fact. This check thus relies on undefined
behavior of signed integer overflows. Fix this by instead checking
up-front whether the multiplications or additions will overflow.

Note that a detected overflow will not cause us to abort parsing the
current sequence of digits. In the case of an overflow, previous
behavior was to still set up the end pointer correctly to point to the
first character immediately after the currently parsed number. We do not
want to change this now as code may rely on the end pointer being set up
correctly even if the parsed number is too big to be represented as
64 bit integer.
@pks-t
Copy link
Member Author

pks-t commented Oct 18, 2018 via email

@pks-t
Copy link
Member Author

pks-t commented Oct 19, 2018

/rebuild

@libgit2-azure-pipelines
Copy link

Okay, @pks-t, I started to rebuild this pull request.

When an integer that is parsed with `git__strntol32` is too big to fit
into an int32, we will generate an error message that includes the
actual string that failed to parse. This does not acknowledge the fact
that the string may either not be NUL terminated or alternative include
additional characters after the number that is to be parsed. We may thus
end up printing characters into the buffer that aren't the number or,
worse, read out of bounds.

Fix the issue by utilizing the `endptr` that was set by
`git__strntol64`. This pointer is guaranteed to be set to the first
character following the number, and we can thus use it to compute the
width of the number that shall be printed. Create a test to verify that
we correctly truncate the number.
@pks-t pks-t force-pushed the pks/strtol-removal branch from d497e7a to ea19efc Compare October 19, 2018 10:19
@ethomson
Copy link
Member

This looks good to me. 👍

@pks-t pks-t merged commit bea6598 into libgit2:master Oct 25, 2018
@pks-t pks-t deleted the pks/strtol-removal branch October 25, 2018 09:21
@pks-t
Copy link
Member Author

pks-t commented Oct 25, 2018

Thanks, Ed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants