Skip to contentSkip to conversation

add-interactive: reject malformed numerical input

PATCH In review Seonghyeon Cho (조성현) via GitGitGadget 3 participants 5 messages Aug 30, 2025 – Sep 8, 2025

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 add-interactive: reject malformed numerical input

From: Seonghyeon Cho <[email protected]>

The list-and-choose interface accepts malformed input such as "2m3" and interprets it as "2-", silently selecting a range to the end. This is misleading and makes it easy to select unintended items.

Reject such input by treating it as invalid.

---
add-interactive: reject malformed numerical input

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2044%2Fsh-cho%2Freject-malformed-input-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2044/sh-cho/reject-malformed-input-v1
Pull-Request: https://github.com/git/git/pull/2044

 add-interactive.c | 2 ++
 1 file changed, 2 insertions(+)
add-interactive.c +2 -0
index 3e692b47ec..86ff632288 100644
@@ -396,6 +396,8 @@ static ssize_t list_and_choose(struct add_i_state *s,
 					if (endp != p + sep)
 						from = -1;
 				}
+				else
+					from = -1;
 			}
 
 			if (p[sep])

base-commit: 6ad802182101d622e6a4132f48292ddfa79e2024

Signature · 1 line
gitgitgadget
#1 lore raw
Quoted 7 lines · Seonghyeon Cho (조성현) via GitGitGadget

From: Seonghyeon Cho <[email protected]>

The list-and-choose interface accepts malformed input such as "2m3" and interprets it as "2-", silently selecting a range to the end. This is misleading and makes it easy to select unintended items.

Reject such input by treating it as invalid.

Okay, that does feel fishy indeed. It would be good though to have a test case that demonstrates the new behaviour and at the same time ensures that we don't regress in the future. You can have a look at "t3701-add-interactive.sh", which has a bunch of other tests for this command, as well.

In general though we're not doing a good job here of error checking. We don't at all verify whether strtoul() returned an error, for example ERANGE. So if a user passes an integer that exceeds whatever we can store in an unsigned long we'll silently proceed with a bogus result, won't we?

Ideally, we'd use a saner interface to parse these integers, like for example our own git_parse_ulong(). But unfortunately, that interface does not handle the case where we only want to parse a substring in a longer string. Too bad.

add-interactive.c static ssize_t list_and_choose(struct add_i_state *s, · line 401

Quoted 11 lines
add-interactive.c +2 -0
index 3e692b47ec..86ff632288 100644
@@ -396,6 +396,8 @@ static ssize_t list_and_choose(struct add_i_state *s,
 					if (endp != p + sep)
 						from = -1;
 				}
+				else
+					from = -1;
 			}

Coding style: the else should sit on the same line as the closing curly brace. And furthermore, if one of the branches of an if-else chain requires curly braces, then all branches should have curly braces.

Patrick

#2 lore raw
Quoted 5 lines · Patrick Steinhardt

Okay, that does feel fishy indeed. It would be good though to have a test case that demonstrates the new behaviour and at the same time ensures that we don't regress in the future. You can have a look at "t3701-add-interactive.sh", which has a bunch of other tests for this command, as well.

Okay, I'll add tests.

Quoted 10 lines

In general though we're not doing a good job here of error checking. We don't at all verify whether strtoul() returned an error, for example ERANGE. So if a user passes an integer that exceeds whatever we can store in an unsigned long we'll silently proceed with a bogus result, won't we?

Ideally, we'd use a saner interface to parse these integers, like for example our own git_parse_ulong(). But unfortunately, that interface does not handle the case where we only want to parse a substring in a longer string. Too bad.

Good point. Would you prefer I introduce new parse method here, or should this be handled in separate patch?

Quoted 3 lines

Coding style: the else should sit on the same line as the closing curly brace. And furthermore, if one of the branches of an if-else chain requires curly braces, then all branches should have curly braces.

Ok, I'll fix coding styles.

Thanks,
Seonghyeon

#3 lore raw
Quoted 7 lines · Seonghyeon Cho
Quoted 6 lines · Patrick Steinhardt

In general though we're not doing a good job here of error checking. We don't at all verify whether strtoul() returned an error, for example ERANGE. So if a user passes an integer that exceeds whatever we can store in an unsigned long we'll silently proceed with a bogus result, won't we?

Quoted 7 lines
Quoted 4 lines

Ideally, we'd use a saner interface to parse these integers, like for example our own git_parse_ulong(). But unfortunately, that interface does not handle the case where we only want to parse a substring in a longer string. Too bad.

Good point. Would you prefer I introduce new parse method here, or should this be handled in separate patch?

I don't think that would need to be part of your patch series. But we should have proper error checking for strtoul() if we're already improving this code.

Patrick

#4 lore raw
Quoted 3 lines · Patrick Steinhardt

I don't think that would need to be part of your patch series. But we should have proper error checking for strtoul() if we're already improving this code.

Understood. I'll handle it too.

Thanks,
Seonghyeon