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)
{
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;

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")",
(uintmax_t)list->items.nr, (uintmax_t)list->sorted.nr);

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

View File

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

#include "git-compat-util.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,
const char *string, size_t len)
{
int i = string_list_find_insert_index(map, string, 1);
if (i < 0) {
/* exact match */
i = -1 - i;
bool exact_match;
size_t i = string_list_find_insert_index(map, string, &exact_match);
if (exact_match) {
if (!string[len])
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
* 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);
if (cmp < 0)
/*

13
refs.c
View File

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

#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS

#include "git-compat-util.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 *skip)
{
int pos;

if (!extras)
return NULL;

@ -1725,7 +1722,7 @@ const char *find_descendant_ref(const char *dirname,
* with dirname (remember, dirname includes the trailing
* 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++) {
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 strbuf buf = STRBUF_INIT;
const char *hook;
int ret = 0, i;
int ret = 0;

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

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];

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,
void *cb_data)
{
int i;

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

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
* inserted */
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;
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)
left = middle + 1;
else {
*exact_match = 1;
if (exact_match)
*exact_match = true;
return middle;
}
}

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

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);

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,
int free_util)
{
int exact_match;
bool exact_match;
int i = get_entry_index(list, string, &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);
return exact_match;
}

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

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)
return NULL;
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: */

/** Determine if the string_list has a given string or not. */
int 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);
bool string_list_has_string(const struct string_list *list, const char *string);

/**
* 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