Merge branch 'tmp-inih' into 'master'

inih: updated to latest version r62

See merge request openconnect/ocserv!437
This commit is contained in:
Nikos Mavrogiannopoulos
2026-01-25 17:01:47 +00:00
3 changed files with 75 additions and 37 deletions

1
NEWS
View File

@@ -1,4 +1,5 @@
* Version 1.4.1 (unreleased)
- The bundled inih was updated to r62.
- occtl: Fix column misalignment in ban command outputs
- Handle dotted client hostnames (e.g., .local) by stripping the domain suffix
- Renamed `min-reauth-time` configuration option to `ban-time` to better reflect

View File

@@ -2,7 +2,7 @@
SPDX-License-Identifier: BSD-3-Clause
Copyright (C) 2009-2020, Ben Hoyt
Copyright (C) 2009-2025, Ben Hoyt
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
@@ -48,17 +48,17 @@ typedef struct {
size_t num_left;
} ini_parse_string_ctx;
/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s)
/* Strip whitespace chars off end of given string, in place. end must be a
pointer to the NUL terminator at the end of the string. Return s. */
static char* ini_rstrip(char* s, char* end)
{
char* p = s + strlen(s);
while (p > s && isspace((unsigned char)(*--p)))
*p = '\0';
while (end > s && isspace((unsigned char)(*--end)))
*end = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s)
static char* ini_lskip(const char* s)
{
while (*s && isspace((unsigned char)(*s)))
s++;
@@ -68,7 +68,7 @@ static char* lskip(const char* s)
/* Return pointer to first char (of chars) or inline comment in given string,
or pointer to NUL at end of string if neither found. Inline comment must
be prefixed by a whitespace character to register as a comment. */
static char* find_chars_or_comment(const char* s, const char* chars)
static char* ini_find_chars_or_comment(const char* s, const char* chars)
{
#if INI_ALLOW_INLINE_COMMENTS
int was_space = 0;
@@ -87,7 +87,7 @@ static char* find_chars_or_comment(const char* s, const char* chars)
/* Similar to strncpy, but ensures dest (size bytes) is
NUL-terminated, and doesn't pad with NULs. */
static char* strncpy0(char* dest, const char* src, size_t size)
static char* ini_strncpy0(char* dest, const char* src, size_t size)
{
/* Could use strncpy internally, but it causes gcc warnings (see issue #91) */
size_t i;
@@ -111,17 +111,20 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
#endif
#if INI_ALLOW_REALLOC && !INI_USE_STACK
char* new_line;
size_t offset;
#endif
char section[MAX_SECTION] = "";
#if INI_ALLOW_MULTILINE
char prev_name[MAX_NAME] = "";
#endif
size_t offset;
char* start;
char* end;
char* name;
char* value;
int lineno = 0;
int error = 0;
char abyss[16]; /* Used to consume input when a line is too long. */
#if !INI_USE_STACK
line = (char*)ini_malloc(INI_INITIAL_ALLOC);
@@ -138,9 +141,11 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
/* Scan through stream line by line */
while (reader(line, (int)max_line, stream) != NULL) {
#if INI_ALLOW_REALLOC && !INI_USE_STACK
offset = strlen(line);
while (offset == max_line - 1 && line[offset - 1] != '\n') {
#if INI_ALLOW_REALLOC && !INI_USE_STACK
while (max_line < INI_MAX_LINE &&
offset == max_line - 1 && line[offset - 1] != '\n') {
max_line *= 2;
if (max_line > INI_MAX_LINE)
max_line = INI_MAX_LINE;
@@ -152,14 +157,22 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
line = new_line;
if (reader(line + offset, (int)(max_line - offset), stream) == NULL)
break;
if (max_line >= INI_MAX_LINE)
break;
offset += strlen(line + offset);
}
#endif
lineno++;
/* If line exceeded INI_MAX_LINE bytes, discard till end of line. */
if (offset == max_line - 1 && line[offset - 1] != '\n') {
while (reader(abyss, sizeof(abyss), stream) != NULL) {
if (!error)
error = lineno;
if (abyss[strlen(abyss) - 1] == '\n')
break;
}
}
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
@@ -168,7 +181,7 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
start += 3;
}
#endif
start = lskip(rstrip(start));
start = ini_rstrip(ini_lskip(start), line + offset);
if (strchr(INI_START_COMMENT_PREFIXES, *start)) {
/* Start-of-line comment */
@@ -176,10 +189,9 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
#if INI_ALLOW_MULTILINE
else if (*prev_name && *start && start > line) {
#if INI_ALLOW_INLINE_COMMENTS
end = find_chars_or_comment(start, NULL);
if (*end)
*end = '\0';
rstrip(start);
end = ini_find_chars_or_comment(start, NULL);
*end = '\0';
ini_rstrip(start, end);
#endif
/* Non-blank line with leading whitespace, treat as continuation
of previous name's value (as per Python configparser). */
@@ -189,11 +201,13 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
#endif
else if (*start == '[') {
/* A "[section]" line */
end = find_chars_or_comment(start + 1, "]");
end = ini_find_chars_or_comment(start + 1, "]");
if (*end == ']') {
*end = '\0';
strncpy0(section, start + 1, sizeof(section));
ini_strncpy0(section, start + 1, sizeof(section));
#if INI_ALLOW_MULTILINE
*prev_name = '\0';
#endif
#if INI_CALL_HANDLER_ON_NEW_SECTION
if (!HANDLER(user, section, NULL, NULL) && !error)
error = lineno;
@@ -206,33 +220,35 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
}
else if (*start) {
/* Not a comment, must be a name[=:]value pair */
end = find_chars_or_comment(start, "=:");
end = ini_find_chars_or_comment(start, "=:");
if (*end == '=' || *end == ':') {
*end = '\0';
name = rstrip(start);
name = ini_rstrip(start, end);
value = end + 1;
#if INI_ALLOW_INLINE_COMMENTS
end = find_chars_or_comment(value, NULL);
if (*end)
*end = '\0';
end = ini_find_chars_or_comment(value, NULL);
*end = '\0';
#endif
value = lskip(value);
rstrip(value);
value = ini_lskip(value);
ini_rstrip(value, end);
#if INI_ALLOW_MULTILINE
ini_strncpy0(prev_name, name, sizeof(prev_name));
#endif
/* Valid name[=:]value pair found, call handler */
strncpy0(prev_name, name, sizeof(prev_name));
if (!HANDLER(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
else {
/* No '=' or ':' found on name[=:]value line */
#if INI_ALLOW_NO_VALUE
*end = '\0';
name = rstrip(start);
name = ini_rstrip(start, end);
if (!HANDLER(user, section, name, NULL) && !error)
error = lineno;
#else
error = lineno;
if (!error)
error = lineno;
#endif
}
}
@@ -279,6 +295,10 @@ static char* ini_reader_string(char* str, int num, void* stream) {
char* strp = str;
char c;
#ifdef __clang_analyzer__
memset(str, '\0', num);
#endif
if (ctx_num_left == 0 || num < 2)
return NULL;
@@ -299,10 +319,16 @@ static char* ini_reader_string(char* str, int num, void* stream) {
/* See documentation in header file. */
int ini_parse_string(const char* string, ini_handler handler, void* user) {
return ini_parse_string_length(string, strlen(string), handler, user);
}
/* See documentation in header file. */
int ini_parse_string_length(const char* string, size_t length,
ini_handler handler, void* user) {
ini_parse_string_ctx ctx;
ctx.ptr = string;
ctx.num_left = strlen(string);
ctx.num_left = length;
return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
user);
}

View File

@@ -2,7 +2,7 @@
SPDX-License-Identifier: BSD-3-Clause
Copyright (C) 2009-2020, Ben Hoyt
Copyright (C) 2009-2025, Ben Hoyt
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
@@ -47,7 +47,13 @@ extern "C" {
#endif
#endif
/* Typedef for prototype of handler function. */
/* Typedef for prototype of handler function.
Note that even though the value parameter has type "const char*", the user
may cast to "char*" and modify its content, as the value is not used again
after the call to ini_handler. This is not true of section and name --
those must not be modified.
*/
#if INI_HANDLER_LINENO
typedef int (*ini_handler)(void* user, const char* section,
const char* name, const char* value,
@@ -86,10 +92,15 @@ INI_API int ini_parse_stream(ini_reader reader, void* stream, ini_handler handle
void* user);
/* Same as ini_parse(), but takes a zero-terminated string with the INI data
instead of a file. Useful for parsing INI data from a network socket or
already in memory. */
instead of a file. Useful for parsing INI data from a network socket or
which is already in memory. */
INI_API int ini_parse_string(const char* string, ini_handler handler, void* user);
/* Same as ini_parse_string(), but takes a string and its length, avoiding
strlen(). Useful for parsing INI data from a network socket or which is
already in memory, or interfacing with C++ std::string_view. */
INI_API int ini_parse_string_length(const char* string, size_t length, ini_handler handler, void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
configparser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed. */