Merge branch 'sj/string-list'

The "string-list" API function to find where a given string would
be inserted got updated so that it can use unrealistically huge
array index that would only fit in size_t but not int or ssize_t
to achieve unstated goal.

* sj/string-list:
  refs: enable sign compare warnings check
  string-list: change "string_list_find_insert_index" return type to "size_t"
  string-list: replace negative index encoding with "exact_match" parameter
  string-list: use bool instead of int for "exact_match"
main
Junio C Hamano 2025-10-14 12:56:08 -07:00
commit 048625a689
5 changed files with 35 additions and 36 deletions

View File

@ -244,7 +244,8 @@ static void find_unique_prefixes(struct prefix_item_list *list)


static ssize_t find_unique(const char *string, struct prefix_item_list *list) static ssize_t find_unique(const char *string, struct prefix_item_list *list)
{ {
int index = string_list_find_insert_index(&list->sorted, string, 1); bool exact_match;
size_t index = string_list_find_insert_index(&list->sorted, string, &exact_match);
struct string_list_item *item; struct string_list_item *item;


if (list->items.nr != list->sorted.nr) if (list->items.nr != list->sorted.nr)
@ -252,8 +253,8 @@ static ssize_t find_unique(const char *string, struct prefix_item_list *list)
" vs %"PRIuMAX")", " vs %"PRIuMAX")",
(uintmax_t)list->items.nr, (uintmax_t)list->sorted.nr); (uintmax_t)list->items.nr, (uintmax_t)list->sorted.nr);


if (index < 0) if (exact_match)
item = list->sorted.items[-1 - index].util; item = list->sorted.items[index].util;
else if (index > 0 && else if (index > 0 &&
starts_with(list->sorted.items[index - 1].string, string)) starts_with(list->sorted.items[index - 1].string, string))
return -1; return -1;

View File

@ -1,5 +1,4 @@
#define USE_THE_REPOSITORY_VARIABLE #define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS


#include "git-compat-util.h" #include "git-compat-util.h"
#include "environment.h" #include "environment.h"
@ -243,10 +242,9 @@ void clear_mailmap(struct string_list *map)
static struct string_list_item *lookup_prefix(struct string_list *map, static struct string_list_item *lookup_prefix(struct string_list *map,
const char *string, size_t len) const char *string, size_t len)
{ {
int i = string_list_find_insert_index(map, string, 1); bool exact_match;
if (i < 0) { size_t i = string_list_find_insert_index(map, string, &exact_match);
/* exact match */ if (exact_match) {
i = -1 - i;
if (!string[len]) if (!string[len])
return &map->items[i]; return &map->items[i];
/* /*
@ -267,7 +265,7 @@ static struct string_list_item *lookup_prefix(struct string_list *map,
* overlong key would be inserted, which must come after the * overlong key would be inserted, which must come after the
* real location of the key if one exists. * real location of the key if one exists.
*/ */
while (0 <= --i && i < map->nr) { while (i-- && i < map->nr) {
int cmp = strncasecmp(map->items[i].string, string, len); int cmp = strncasecmp(map->items[i].string, string, len);
if (cmp < 0) if (cmp < 0)
/* /*

13
refs.c
View File

@ -3,7 +3,6 @@
*/ */


#define USE_THE_REPOSITORY_VARIABLE #define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS


#include "git-compat-util.h" #include "git-compat-util.h"
#include "advice.h" #include "advice.h"
@ -1714,8 +1713,6 @@ const char *find_descendant_ref(const char *dirname,
const struct string_list *extras, const struct string_list *extras,
const struct string_list *skip) const struct string_list *skip)
{ {
int pos;

if (!extras) if (!extras)
return NULL; return NULL;


@ -1725,7 +1722,7 @@ const char *find_descendant_ref(const char *dirname,
* with dirname (remember, dirname includes the trailing * with dirname (remember, dirname includes the trailing
* slash) and is not in skip, then we have a conflict. * slash) and is not in skip, then we have a conflict.
*/ */
for (pos = string_list_find_insert_index(extras, dirname, 0); for (size_t pos = string_list_find_insert_index(extras, dirname, NULL);
pos < extras->nr; pos++) { pos < extras->nr; pos++) {
const char *extra_refname = extras->items[pos].string; const char *extra_refname = extras->items[pos].string;


@ -2414,7 +2411,7 @@ static int run_transaction_hook(struct ref_transaction *transaction,
struct child_process proc = CHILD_PROCESS_INIT; struct child_process proc = CHILD_PROCESS_INIT;
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
const char *hook; const char *hook;
int ret = 0, i; int ret = 0;


hook = find_hook(transaction->ref_store->repo, "reference-transaction"); hook = find_hook(transaction->ref_store->repo, "reference-transaction");
if (!hook) if (!hook)
@ -2431,7 +2428,7 @@ static int run_transaction_hook(struct ref_transaction *transaction,


sigchain_push(SIGPIPE, SIG_IGN); sigchain_push(SIGPIPE, SIG_IGN);


for (i = 0; i < transaction->nr; i++) { for (size_t i = 0; i < transaction->nr; i++) {
struct ref_update *update = transaction->updates[i]; struct ref_update *update = transaction->updates[i];


if (update->flags & REF_LOG_ONLY) if (update->flags & REF_LOG_ONLY)
@ -2824,9 +2821,7 @@ void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
ref_transaction_for_each_queued_update_fn cb, ref_transaction_for_each_queued_update_fn cb,
void *cb_data) void *cb_data)
{ {
int i; for (size_t i = 0; i < transaction->nr; i++) {

for (i = 0; i < transaction->nr; i++) {
struct ref_update *update = transaction->updates[i]; struct ref_update *update = transaction->updates[i];


cb(update->refname, cb(update->refname,

View File

@ -16,7 +16,7 @@ void string_list_init_dup(struct string_list *list)
/* if there is no exact match, point to the index where the entry could be /* if there is no exact match, point to the index where the entry could be
* inserted */ * inserted */
static size_t get_entry_index(const struct string_list *list, const char *string, static size_t get_entry_index(const struct string_list *list, const char *string,
int *exact_match) bool *exact_match)
{ {
size_t left = 0, right = list->nr; size_t left = 0, right = list->nr;
compare_strings_fn cmp = list->cmp ? list->cmp : strcmp; compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
@ -29,18 +29,20 @@ static size_t get_entry_index(const struct string_list *list, const char *string
else if (compare > 0) else if (compare > 0)
left = middle + 1; left = middle + 1;
else { else {
*exact_match = 1; if (exact_match)
*exact_match = true;
return middle; return middle;
} }
} }


*exact_match = 0; if (exact_match)
*exact_match = false;
return right; return right;
} }


static size_t add_entry(struct string_list *list, const char *string) static size_t add_entry(struct string_list *list, const char *string)
{ {
int exact_match = 0; bool exact_match;
size_t index = get_entry_index(list, string, &exact_match); size_t index = get_entry_index(list, string, &exact_match);


if (exact_match) if (exact_match)
@ -68,7 +70,7 @@ struct string_list_item *string_list_insert(struct string_list *list, const char
void string_list_remove(struct string_list *list, const char *string, void string_list_remove(struct string_list *list, const char *string,
int free_util) int free_util)
{ {
int exact_match; bool exact_match;
int i = get_entry_index(list, string, &exact_match); int i = get_entry_index(list, string, &exact_match);


if (exact_match) { if (exact_match) {
@ -82,26 +84,23 @@ void string_list_remove(struct string_list *list, const char *string,
} }
} }


int string_list_has_string(const struct string_list *list, const char *string) bool string_list_has_string(const struct string_list *list, const char *string)
{ {
int exact_match; bool exact_match;
get_entry_index(list, string, &exact_match); get_entry_index(list, string, &exact_match);
return exact_match; return exact_match;
} }


int string_list_find_insert_index(const struct string_list *list, const char *string, size_t string_list_find_insert_index(const struct string_list *list, const char *string,
int negative_existing_index) bool *exact_match)
{ {
int exact_match; return get_entry_index(list, string, exact_match);
int index = get_entry_index(list, string, &exact_match);
if (exact_match)
index = -1 - (negative_existing_index ? index : 0);
return index;
} }


struct string_list_item *string_list_lookup(struct string_list *list, const char *string) struct string_list_item *string_list_lookup(struct string_list *list, const char *string)
{ {
int exact_match, i = get_entry_index(list, string, &exact_match); bool exact_match;
size_t i = get_entry_index(list, string, &exact_match);
if (!exact_match) if (!exact_match)
return NULL; return NULL;
return list->items + i; return list->items + i;

View File

@ -172,9 +172,15 @@ void string_list_remove_empty_items(struct string_list *list, int free_util);
/* Use these functions only on sorted lists: */ /* Use these functions only on sorted lists: */


/** Determine if the string_list has a given string or not. */ /** Determine if the string_list has a given string or not. */
int string_list_has_string(const struct string_list *list, const char *string); bool string_list_has_string(const struct string_list *list, const char *string);
int string_list_find_insert_index(const struct string_list *list, const char *string,
int negative_existing_index); /**
* Find the index at which a new element should be inserted into the
* string_list to maintain sorted order. If exact_match is not NULL,
* it will be set to true if the string already exists in the list.
*/
size_t string_list_find_insert_index(const struct string_list *list, const char *string,
bool *exact_match);


/** /**
* Insert a new element to the string_list. The returned pointer can * Insert a new element to the string_list. The returned pointer can