diff mbox series

[7/9] builtin/log: fix remaining -Wsign-compare warnings

Message ID 20241227-b4-pks-commit-reach-sign-compare-v1-7-07c59c2aa632@pks.im (mailing list archive)
State New
Headers show
Series commit-reach: -Wsign-compare follow-ups | expand

Commit Message

Patrick Steinhardt Dec. 27, 2024, 10:46 a.m. UTC
Fix remaining -Wsign-compare warnings in "builtin/log.c" and mark the
file as -Wsign-compare-clean. While most of the fixes are obvious, one
fix requires us to use `cast_size_t_to_int()`, which will cause us to
die in case the `size_t` cannot be represented as `int`. This should be
fine though, as the data would typically be set either via a config key
or via the command line, neither of which should ever exceed a couple of
kilobytes of data.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/log.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

Comments

shejialuo Dec. 27, 2024, 1:21 p.m. UTC | #1
On Fri, Dec 27, 2024 at 11:46:27AM +0100, Patrick Steinhardt wrote:

[snip]

> @@ -717,14 +715,14 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
>  	unsigned long size;
>  	enum object_type type;
>  	char *buf = repo_read_object_file(the_repository, oid, &type, &size);
> -	int offset = 0;
> +	unsigned long offset = 0;

Why here we use `unsigned long`, is this a special situation where we
cannot use `size_t`?

>  
>  	if (!buf)
>  		return error(_("could not read object %s"), oid_to_hex(oid));
>  
>  	assert(type == OBJ_TAG);
>  	while (offset < size && buf[offset] != '\n') {
> -		int new_offset = offset + 1;
> +		unsigned long new_offset = offset + 1;
>  		const char *ident;
>  		while (new_offset < size && buf[new_offset++] != '\n')
>  			; /* do nothing */

> @@ -2183,7 +2182,7 @@ int cmd_format_patch(int argc,
>  		fmt_patch_suffix = cfg.fmt_patch_suffix;
>  
>  	/* Make sure "0000-$sub.patch" gives non-negative length for $sub */
> -	if (cfg.log.fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
> +	if (cfg.log.fmt_patch_name_max <= cast_size_t_to_int(strlen("0000-") + strlen(fmt_patch_suffix)))

A design question, why we don't change the type of
`cfg.log.fmt_patch_name_max` to be `size_t`?

>  		cfg.log.fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix);
>  
>  	if (cover_from_description_arg)
> 
> -- 
> 2.48.0.rc0.184.g0fc57dec57.dirty
> 

Thanks,
Jialuo
Patrick Steinhardt Dec. 27, 2024, 1:57 p.m. UTC | #2
On Fri, Dec 27, 2024 at 09:21:56PM +0800, shejialuo wrote:
> On Fri, Dec 27, 2024 at 11:46:27AM +0100, Patrick Steinhardt wrote:
> > @@ -717,14 +715,14 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
> >  	unsigned long size;
> >  	enum object_type type;
> >  	char *buf = repo_read_object_file(the_repository, oid, &type, &size);
> > -	int offset = 0;
> > +	unsigned long offset = 0;
> 
> Why here we use `unsigned long`, is this a special situation where we
> cannot use `size_t`?

Mostly because other variables already use `unsigned long` here,
including `repo_read_object_file()`. So given that our object layer
doesn't support `size_t` it wouldn't make sense to use it for the
offset, either.

> >  
> >  	if (!buf)
> >  		return error(_("could not read object %s"), oid_to_hex(oid));
> >  
> >  	assert(type == OBJ_TAG);
> >  	while (offset < size && buf[offset] != '\n') {
> > -		int new_offset = offset + 1;
> > +		unsigned long new_offset = offset + 1;
> >  		const char *ident;
> >  		while (new_offset < size && buf[new_offset++] != '\n')
> >  			; /* do nothing */
> 
> > @@ -2183,7 +2182,7 @@ int cmd_format_patch(int argc,
> >  		fmt_patch_suffix = cfg.fmt_patch_suffix;
> >  
> >  	/* Make sure "0000-$sub.patch" gives non-negative length for $sub */
> > -	if (cfg.log.fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
> > +	if (cfg.log.fmt_patch_name_max <= cast_size_t_to_int(strlen("0000-") + strlen(fmt_patch_suffix)))
> 
> A design question, why we don't change the type of
> `cfg.log.fmt_patch_name_max` to be `size_t`?

The whole infra around this uses `int`s, too, so changing this variable
here alone wouldn't suffice. We'd also have to adapt option handling,
config handling, `struct rev_info::patch_name_max` and other bits and
pieces. So in the end the size of required changes would likely balloon
and thus I decided to not go down this rabbit hole.

Patrick
shejialuo Dec. 27, 2024, 2:03 p.m. UTC | #3
On Fri, Dec 27, 2024 at 02:57:18PM +0100, Patrick Steinhardt wrote:
> On Fri, Dec 27, 2024 at 09:21:56PM +0800, shejialuo wrote:
> > On Fri, Dec 27, 2024 at 11:46:27AM +0100, Patrick Steinhardt wrote:
> > > @@ -717,14 +715,14 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
> > >  	unsigned long size;
> > >  	enum object_type type;
> > >  	char *buf = repo_read_object_file(the_repository, oid, &type, &size);
> > > -	int offset = 0;
> > > +	unsigned long offset = 0;
> > 
> > Why here we use `unsigned long`, is this a special situation where we
> > cannot use `size_t`?
> 
> Mostly because other variables already use `unsigned long` here,
> including `repo_read_object_file()`. So given that our object layer
> doesn't support `size_t` it wouldn't make sense to use it for the
> offset, either.
> 

Make sense. Thanks for the explanation.

> > >  
> > >  	if (!buf)
> > >  		return error(_("could not read object %s"), oid_to_hex(oid));
> > >  
> > >  	assert(type == OBJ_TAG);
> > >  	while (offset < size && buf[offset] != '\n') {
> > > -		int new_offset = offset + 1;
> > > +		unsigned long new_offset = offset + 1;
> > >  		const char *ident;
> > >  		while (new_offset < size && buf[new_offset++] != '\n')
> > >  			; /* do nothing */
> > 
> > > @@ -2183,7 +2182,7 @@ int cmd_format_patch(int argc,
> > >  		fmt_patch_suffix = cfg.fmt_patch_suffix;
> > >  
> > >  	/* Make sure "0000-$sub.patch" gives non-negative length for $sub */
> > > -	if (cfg.log.fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
> > > +	if (cfg.log.fmt_patch_name_max <= cast_size_t_to_int(strlen("0000-") + strlen(fmt_patch_suffix)))
> > 
> > A design question, why we don't change the type of
> > `cfg.log.fmt_patch_name_max` to be `size_t`?
> 
> The whole infra around this uses `int`s, too, so changing this variable
> here alone wouldn't suffice. We'd also have to adapt option handling,
> config handling, `struct rev_info::patch_name_max` and other bits and
> pieces. So in the end the size of required changes would likely balloon
> and thus I decided to not go down this rabbit hole.
> 

Yes, I agree. If we do this, there is a lot of efforts we need to deal
with.

> Patrick
diff mbox series

Patch

diff --git a/builtin/log.c b/builtin/log.c
index 805b2355d964915732edf5928d54fb6d06e394d4..a4f41aafcae069541ee987dc94d245edfe9787a8 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -6,7 +6,6 @@ 
  */
 
 #define USE_THE_REPOSITORY_VARIABLE
-#define DISABLE_SIGN_COMPARE_WARNINGS
 
 #include "builtin.h"
 #include "abspath.h"
@@ -209,7 +208,6 @@  static void cmd_log_init_defaults(struct rev_info *rev,
 
 static void set_default_decoration_filter(struct decoration_filter *decoration_filter)
 {
-	int i;
 	char *value = NULL;
 	struct string_list *include = decoration_filter->include_ref_pattern;
 	const struct string_list *config_exclude;
@@ -243,7 +241,7 @@  static void set_default_decoration_filter(struct decoration_filter *decoration_f
 	 * No command-line or config options were given, so
 	 * populate with sensible defaults.
 	 */
-	for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
+	for (size_t i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
 		if (!ref_namespace[i].decoration)
 			continue;
 
@@ -717,14 +715,14 @@  static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
 	unsigned long size;
 	enum object_type type;
 	char *buf = repo_read_object_file(the_repository, oid, &type, &size);
-	int offset = 0;
+	unsigned long offset = 0;
 
 	if (!buf)
 		return error(_("could not read object %s"), oid_to_hex(oid));
 
 	assert(type == OBJ_TAG);
 	while (offset < size && buf[offset] != '\n') {
-		int new_offset = offset + 1;
+		unsigned long new_offset = offset + 1;
 		const char *ident;
 		while (new_offset < size && buf[new_offset++] != '\n')
 			; /* do nothing */
@@ -1316,24 +1314,25 @@  static void print_signature(const char *signature, FILE *file)
 
 static char *find_branch_name(struct rev_info *rev)
 {
-	int i, positive = -1;
 	struct object_id branch_oid;
 	const struct object_id *tip_oid;
 	const char *ref, *v;
 	char *full_ref, *branch = NULL;
+	int interesting_found = 0;
+	size_t idx;
 
-	for (i = 0; i < rev->cmdline.nr; i++) {
+	for (size_t i = 0; i < rev->cmdline.nr; i++) {
 		if (rev->cmdline.rev[i].flags & UNINTERESTING)
 			continue;
-		if (positive < 0)
-			positive = i;
-		else
+		if (interesting_found)
 			return NULL;
+		interesting_found = 1;
+		idx = i;
 	}
-	if (positive < 0)
+	if (!interesting_found)
 		return NULL;
-	ref = rev->cmdline.rev[positive].name;
-	tip_oid = &rev->cmdline.rev[positive].item->oid;
+	ref = rev->cmdline.rev[idx].name;
+	tip_oid = &rev->cmdline.rev[idx].item->oid;
 	if (repo_dwim_ref(the_repository, ref, strlen(ref), &branch_oid,
 			  &full_ref, 0) &&
 	    skip_prefix(full_ref, "refs/heads/", &v) &&
@@ -2183,7 +2182,7 @@  int cmd_format_patch(int argc,
 		fmt_patch_suffix = cfg.fmt_patch_suffix;
 
 	/* Make sure "0000-$sub.patch" gives non-negative length for $sub */
-	if (cfg.log.fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
+	if (cfg.log.fmt_patch_name_max <= cast_size_t_to_int(strlen("0000-") + strlen(fmt_patch_suffix)))
 		cfg.log.fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix);
 
 	if (cover_from_description_arg)