Main: include/kernaux/ntoa.h: Protect from too long prefix

This commit is contained in:
Alex Kotov 2022-06-01 15:45:36 +03:00
parent 4c326463ac
commit 9ec149a12d
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
9 changed files with 98 additions and 22 deletions

View File

@ -1,3 +1,7 @@
2022-06-31 Alex Kotov <kotovalexarian@gmail.com>
* include/kernaux/ntoa.h: Protect from too long prefix
2022-05-30 Alex Kotov <kotovalexarian@gmail.com>
* include/kernaux/ntoa.h: Functions "kernaux_utoa" and "kernaux_itoa"

View File

@ -7,6 +7,8 @@ extern "C" {
#include <stdint.h>
#define KERNAUX_NTOA_MAX_PREFIX_LEN 100
#define KERNAUX_NTOA_DEFAULT_PREFIX_2 "0b"
#define KERNAUX_NTOA_DEFAULT_PREFIX_8 "0o"
#define KERNAUX_NTOA_DEFAULT_PREFIX_16 "0x"

View File

@ -9,8 +9,6 @@
#include <mruby/presym.h>
#include <mruby/string.h>
#define MAX_PREFIX_LEN 100
static mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self);
@ -77,7 +75,7 @@ mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self)
mrb_raise(mrb, E_RANGE_ERROR,
"can't convert negative number to uint64_t");
}
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_TooLongNtoaPrefixError =
@ -108,7 +106,7 @@ mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self)
mrb_int prefix_len = 0;
mrb_get_args(mrb, "io|s!", &value, &base, &prefix, &prefix_len);
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_TooLongNtoaPrefixError =

View File

@ -1,8 +1,6 @@
#include <kernaux.h>
#include <ruby.h>
#define MAX_PREFIX_LEN 100
#ifdef HAVE_KERNAUX_UTOA
static VALUE rb_KernAux_utoa(int argc, const VALUE *argv, VALUE self);
#endif
@ -139,7 +137,7 @@ VALUE rb_KernAux_utoa(const int argc, const VALUE *argv, const VALUE self)
prefix = StringValueCStr(prefix_rb);
prefix_len = RSTRING_LEN(prefix_rb);
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
rb_raise(
rb_KernAux_TooLongNtoaPrefixError,
"prefix length %ld is too long",
@ -177,7 +175,7 @@ VALUE rb_KernAux_itoa(const int argc, const VALUE *argv, const VALUE self)
prefix = StringValueCStr(prefix_rb);
prefix_len = RSTRING_LEN(prefix_rb);
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) {
rb_raise(
rb_KernAux_TooLongNtoaPrefixError,
"prefix length %ld is too long",

View File

@ -7,4 +7,4 @@ pub mod assert;
pub mod ntoa;
pub use assert::*;
pub use ntoa::*;
pub use ntoa::{MAX_PREFIX_LEN as NTOA_MAX_PREFIX_LEN, *};

View File

@ -1,5 +1,7 @@
use libc::{c_char, c_int};
pub const MAX_PREFIX_LEN: usize = 100;
pub const UTOA_MIN_BUFFER_SIZE: usize = 64 + 1;
pub const ITOA_MIN_BUFFER_SIZE: usize = 65 + 1;

View File

@ -1,9 +1,9 @@
use kernaux_sys::{
use kernaux_sys::ntoa::{
itoa as kernaux_itoa, itoa10 as kernaux_itoa10, itoa16 as kernaux_itoa16,
itoa2 as kernaux_itoa2, itoa8 as kernaux_itoa8, utoa as kernaux_utoa,
utoa10 as kernaux_utoa10, utoa16 as kernaux_utoa16, utoa2 as kernaux_utoa2,
utoa8 as kernaux_utoa8, ITOA10_BUFFER_SIZE, ITOA16_BUFFER_SIZE,
ITOA2_BUFFER_SIZE, ITOA8_BUFFER_SIZE, ITOA_MIN_BUFFER_SIZE,
ITOA2_BUFFER_SIZE, ITOA8_BUFFER_SIZE, ITOA_MIN_BUFFER_SIZE, MAX_PREFIX_LEN,
UTOA10_BUFFER_SIZE, UTOA16_BUFFER_SIZE, UTOA2_BUFFER_SIZE,
UTOA8_BUFFER_SIZE, UTOA_MIN_BUFFER_SIZE,
};
@ -33,13 +33,13 @@ pub fn utoa(
prefix: Option<&str>,
) -> Result<String, Error> {
if let Some(prefix) = prefix {
if prefix.len() > 100 {
if prefix.len() > MAX_PREFIX_LEN {
return Err(Error::PrefixTooLong(prefix.len()));
}
}
let mut buffer: [i8; UTOA_MIN_BUFFER_SIZE + 100] =
[0; UTOA_MIN_BUFFER_SIZE + 100];
let mut buffer: [i8; UTOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN] =
[0; UTOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN];
let prefix = if let Some(prefix) = prefix {
Some(CString::new(prefix)?)
@ -66,13 +66,13 @@ pub fn itoa(
prefix: Option<&str>,
) -> Result<String, Error> {
if let Some(prefix) = prefix {
if prefix.len() > 100 {
if prefix.len() > MAX_PREFIX_LEN {
return Err(Error::PrefixTooLong(prefix.len()));
}
}
let mut buffer: [i8; ITOA_MIN_BUFFER_SIZE + 100] =
[0; ITOA_MIN_BUFFER_SIZE + 100];
let mut buffer: [i8; ITOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN] =
[0; ITOA_MIN_BUFFER_SIZE + MAX_PREFIX_LEN];
let prefix = if let Some(prefix) = prefix {
Some(CString::new(prefix)?)

View File

@ -32,7 +32,16 @@ char *kernaux_utoa(uint64_t value, char *buffer, int base, const char *prefix)
KERNAUX_ASSERT_RETVAL(base >= 2 && base <= 36, NULL);
// Write prefix
if (prefix) while (*prefix) *(buffer++) = *(prefix++);
if (prefix) {
for (size_t prefix_len = 1; *prefix; ++prefix_len) {
if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN) {
// Protect caller from invalid state
*buffer = '\0';
KERNAUX_PANIC_RETVAL(prefix is too long, NULL);
}
*(buffer++) = *(prefix++);
}
}
// Write number
char *pos = buffer;

View File

@ -9,6 +9,9 @@
#include <stddef.h>
#include <string.h>
#define VALID_LONG_PREFIX "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#define TOO_LONG_PREFIX "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
static const struct {
const char *result;
int base;
@ -512,15 +515,21 @@ static const struct {
static unsigned int assert_count_exp = 0;
static unsigned int assert_count_ctr = 0;
static const char *assert_last_file = NULL;
static int assert_last_line = 0;
static const char *assert_last_msg = NULL;
static void assert_cb(
const char *const file,
const int line __attribute__((unused)),
const char *const msg __attribute__((unused))
const int line,
const char *const msg
) {
++assert_count_ctr;
assert_last_file = file;
assert_last_line = line;
assert_last_msg = msg;
}
static void test_utoa_assert(char *const buffer, const int base)
@ -528,6 +537,12 @@ static void test_utoa_assert(char *const buffer, const int base)
assert(kernaux_utoa(0, buffer, base, NULL) == NULL);
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);
assert(assert_last_msg != NULL);
assert_last_file = NULL;
assert_last_line = 0;
assert_last_msg = NULL;
}
static void test_itoa_assert(char *const buffer, const int base)
@ -535,6 +550,12 @@ static void test_itoa_assert(char *const buffer, const int base)
assert(kernaux_itoa(0, buffer, base, NULL) == NULL);
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);
assert(assert_last_msg != NULL);
assert_last_file = NULL;
assert_last_line = 0;
assert_last_msg = NULL;
}
static const char *str_end(const char *str)
@ -547,7 +568,28 @@ int main()
kernaux_assert_cb = assert_cb;
{
char buffer[KERNAUX_UTOA_MIN_BUFFER_SIZE];
char buffer[KERNAUX_UTOA_MIN_BUFFER_SIZE + KERNAUX_NTOA_MAX_PREFIX_LEN];
const char *const end1 =
kernaux_utoa(123, buffer, 'd', VALID_LONG_PREFIX);
assert(strcmp(buffer, VALID_LONG_PREFIX"123") == 0);
assert(end1 == str_end(buffer));
assert(assert_count_ctr == assert_count_exp);
assert(assert_last_file == NULL);
assert(assert_last_line == 0);
assert(assert_last_msg == NULL);
const char *const end2 =
kernaux_utoa(123, buffer, 'd', TOO_LONG_PREFIX);
assert(strcmp(buffer, VALID_LONG_PREFIX) == 0);
assert(end2 == NULL);
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);
assert(strcmp(assert_last_msg, "prefix is too long") == 0);
assert_last_file = NULL;
assert_last_line = 0;
assert_last_msg = NULL;
test_utoa_assert(NULL, 'd');
test_utoa_assert(buffer, 0);
@ -558,7 +600,28 @@ int main()
}
{
char buffer[KERNAUX_ITOA_MIN_BUFFER_SIZE];
char buffer[KERNAUX_ITOA_MIN_BUFFER_SIZE + KERNAUX_NTOA_MAX_PREFIX_LEN];
const char *const end1 =
kernaux_itoa(123, buffer, 'd', VALID_LONG_PREFIX);
assert(strcmp(buffer, VALID_LONG_PREFIX"123") == 0);
assert(end1 == str_end(buffer));
assert(assert_count_ctr == assert_count_exp);
assert(assert_last_file == NULL);
assert(assert_last_line == 0);
assert(assert_last_msg == NULL);
const char *const end2 =
kernaux_itoa(123, buffer, 'd', TOO_LONG_PREFIX);
assert(strcmp(buffer, VALID_LONG_PREFIX) == 0);
assert(end2 == NULL);
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);
assert(strcmp(assert_last_msg, "prefix is too long") == 0);
assert_last_file = NULL;
assert_last_line = 0;
assert_last_msg = NULL;
test_itoa_assert(NULL, 'd');
test_itoa_assert(buffer, 0);