Ownership handling of the "remote name" buffer given to `remote_get` is inconsistent
- From
Mike Hommey <mh@glandium.org>
- Date
- Jun 19, 2024, 19:53 UTC
- Message-ID
- <20240619195311.yhmbv5ruixa433rn@glandium.org>
Hi,
I actually found this a few years ago, but didn't worry too much about it, forgot about it, then rediscovered it yesterday. I tried to untangle the situation, but it looks like it would take me more time than I can allocate, so I'm sending this report.
When you call `remote_get(name)`, you may end up giving ownership of `name` to the remote, such that if you `free(name)`, using the remote after that may lead to use-after-free. Of course, this is a use-libgit-as-a-library situation; I don't think it happens in actual git code.
Here's how it goes: if your `name` is actually a URL, you end up in this case in remotes_remote_get_1:
if (name_given && !valid_remote(ret))
add_url_alias(remote_state, ret, name);`add_url_alias` will eventually set `ret->url` to contain `name` as-is, taking ownership. Later `release_clear` will free it, which will lead to double-free if the caller frees it.
It's further complicated by `add_url_alias` also sometimes *not* taking ownership, in the face of URL rewrites (in `alias_url`). Meaning, the fix is not as straightforward as changing the above to
add_url_alias(remote_state, ret, xstrdup(name));
This is as far as I went before my time was up on this issue.
Mike