ladybird/Userland/Libraries/LibC/getsubopt.cpp
sin-ack c70f45ff44 Everywhere: Explicitly specify the size in StringView constructors
This commit moves the length calculations out to be directly on the
StringView users. This is an important step towards the goal of removing
StringView(char const*), as it moves the responsibility of calculating
the size of the string to the user of the StringView (which will prevent
naive uses causing OOB access).
2022-07-12 23:11:35 +02:00

53 lines
1.8 KiB
C++

/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ScopeGuard.h>
#include <AK/StringView.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsubopt.html
int getsubopt(char** option_array, char* const* tokens, char** option_value)
{
if (**option_array == '\0')
return -1;
auto const* option_ptr = *option_array;
StringView option_string { option_ptr, strlen(option_ptr) };
auto possible_comma_location = option_string.find(',');
char* option_end = const_cast<char*>(option_string.characters_without_null_termination()) + possible_comma_location.value_or(option_string.length());
auto possible_equals_char_location = option_string.find('=');
char* value_start = option_end;
if (possible_equals_char_location.has_value()) {
value_start = const_cast<char*>(option_string.characters_without_null_termination()) + possible_equals_char_location.value();
}
ScopeGuard ensure_end_array_contains_null_char([&]() {
if (*option_end != '\0')
*option_end++ = '\0';
*option_array = option_end;
});
for (int count = 0; tokens[count] != NULL; ++count) {
auto const* token = tokens[count];
StringView token_stringview { token, strlen(token) };
if (!option_string.starts_with(token_stringview))
continue;
if (tokens[count][value_start - *option_array] != '\0')
continue;
*option_value = value_start != option_end ? value_start + 1 : nullptr;
return count;
}
// Note: The current sub-option does not match any option, so prepare to tell this
// to the application.
*option_value = *option_array;
return -1;
}