mirror of https://github.com/ARMmbed/mbed-os.git
[BUGFIX][IOTUC-18] Library fixes
This commit adds mostly integer (and buffer) overflow checks for the current buffer index (`result` variable).pull/11051/head
parent
de7024f7ab
commit
a5f07166f9
|
@ -17,6 +17,7 @@
|
||||||
#include "mbed_printf_implementation.h"
|
#include "mbed_printf_implementation.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
/***************************/
|
/***************************/
|
||||||
/* MBED */
|
/* MBED */
|
||||||
|
@ -126,9 +127,9 @@ typedef enum {
|
||||||
static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value);
|
static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value);
|
||||||
static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value);
|
static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value);
|
||||||
static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value);
|
static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value);
|
||||||
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value);
|
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value);
|
||||||
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character);
|
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character);
|
||||||
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string);
|
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Print signed integer.
|
* @brief Print signed integer.
|
||||||
|
@ -141,7 +142,7 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in
|
||||||
static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value)
|
static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value)
|
||||||
{
|
{
|
||||||
/* only continue if buffer can fit at least 1 characters */
|
/* only continue if buffer can fit at least 1 characters */
|
||||||
if ((size_t)(*result + 1) <= length)
|
if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length))
|
||||||
{
|
{
|
||||||
MBED_UNSIGNED_STORAGE new_value = 0;
|
MBED_UNSIGNED_STORAGE new_value = 0;
|
||||||
|
|
||||||
|
@ -184,7 +185,7 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in
|
||||||
static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value)
|
static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value)
|
||||||
{
|
{
|
||||||
/* only continue if buffer can fit at least 1 characters */
|
/* only continue if buffer can fit at least 1 characters */
|
||||||
if ((size_t)(*result + 1) <= length)
|
if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length))
|
||||||
{
|
{
|
||||||
/* treat 0 as a corner case */
|
/* treat 0 as a corner case */
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
|
@ -218,7 +219,7 @@ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write scratch pad to buffer or output */
|
/* write scratch pad to buffer or output */
|
||||||
for ( ; ((size_t)*result < length) && (index > 0); index--)
|
for ( ; (*result <= INT_MAX- 1) && ((size_t)*result < length) && (index > 0); index--)
|
||||||
{
|
{
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
|
@ -248,7 +249,7 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt
|
||||||
bool print_leading_zero = false;
|
bool print_leading_zero = false;
|
||||||
|
|
||||||
/* only continue each loop if buffer can fit at least 2 characters */
|
/* only continue each loop if buffer can fit at least 2 characters */
|
||||||
for (int index = 7; (((size_t)(*result + 2) <= length)) && (index >= 0); index--)
|
for (int index = 7; (*result >= 0) && (*result <= INT_MAX - 2) && ((size_t)*result + 2 <= length) && (index >= 0); index--)
|
||||||
{
|
{
|
||||||
/* get most significant byte */
|
/* get most significant byte */
|
||||||
uint8_t output = value >> (8 * index);
|
uint8_t output = value >> (8 * index);
|
||||||
|
@ -290,10 +291,11 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt
|
||||||
* @param result The current output location.
|
* @param result The current output location.
|
||||||
* @param[in] value The pointer to be printed.
|
* @param[in] value The pointer to be printed.
|
||||||
*/
|
*/
|
||||||
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value)
|
static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value)
|
||||||
{
|
{
|
||||||
/* only continue if buffer can fit '0x' and twice the size of a void* */
|
/* only continue if buffer can fit '0x' and twice the size of a void* */
|
||||||
if ((*result + 2 + 2 * sizeof(void*)) <= length)
|
size_t needed = 2 + 2 * sizeof(void*);
|
||||||
|
if ((*result >= 0) && ((size_t)*result <= INT_MAX - needed) && ((size_t)*result + needed <= length))
|
||||||
{
|
{
|
||||||
/* write leading 0x */
|
/* write leading 0x */
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
@ -326,7 +328,7 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng
|
||||||
static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value)
|
static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value)
|
||||||
{
|
{
|
||||||
/* only continue if buffer can fit at least 1 characters */
|
/* only continue if buffer can fit at least 1 characters */
|
||||||
if ((size_t)(*result + 1) <= length)
|
if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length))
|
||||||
{
|
{
|
||||||
/* get integer part */
|
/* get integer part */
|
||||||
MBED_SIGNED_STORAGE integer = value;
|
MBED_SIGNED_STORAGE integer = value;
|
||||||
|
@ -385,7 +387,7 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in
|
||||||
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character)
|
static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character)
|
||||||
{
|
{
|
||||||
/* only continue if the buffer can fit 1 character */
|
/* only continue if the buffer can fit 1 character */
|
||||||
if ((size_t)(*result + 1) <= length)
|
if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length))
|
||||||
{
|
{
|
||||||
/* write character */
|
/* write character */
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
@ -422,10 +424,10 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length,
|
||||||
* @param result The current output location.
|
* @param result The current output location.
|
||||||
* @param[in] value The string to be printed.
|
* @param[in] value The string to be printed.
|
||||||
*/
|
*/
|
||||||
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string)
|
static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string)
|
||||||
{
|
{
|
||||||
/* only continue if the buffer can fit at least 1 character */
|
/* only continue if the buffer can fit at least 1 character */
|
||||||
if ((size_t)(*result + 1) <= length)
|
if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length))
|
||||||
{
|
{
|
||||||
/* count characters in string */
|
/* count characters in string */
|
||||||
size_t remaining = length - *result;
|
size_t remaining = length - *result;
|
||||||
|
@ -440,6 +442,11 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in
|
||||||
/* copy string to buffer */
|
/* copy string to buffer */
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
|
/* ensure that the value of "result" doesn't overflow */
|
||||||
|
if (string_length + *result > INT_MAX)
|
||||||
|
{
|
||||||
|
string_length = (size_t)INT_MAX - *result;
|
||||||
|
}
|
||||||
for (size_t index = 0; index < string_length; index++)
|
for (size_t index = 0; index < string_length; index++)
|
||||||
{
|
{
|
||||||
buffer[*result + index] = string[index];
|
buffer[*result + index] = string[index];
|
||||||
|
@ -476,277 +483,276 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
/* if writing to buffer, reserve space for NULL termination */
|
/* ensure that function wasn't called with an empty buffer, or with
|
||||||
if (buffer)
|
a buffer size that is larger than the maximum 'int' value */
|
||||||
|
if (length > 0 && length <= INT_MAX)
|
||||||
{
|
{
|
||||||
length--;
|
/* parse string */
|
||||||
}
|
for (size_t index = 0; format[index] != '\0'; index++)
|
||||||
|
|
||||||
/* parse string */
|
|
||||||
for (size_t index = 0; format[index] != '\0'; index++)
|
|
||||||
{
|
|
||||||
/* format specifier begin */
|
|
||||||
if (format[index] == '%')
|
|
||||||
{
|
{
|
||||||
size_t next_index = index + 1;
|
/* format specifier begin */
|
||||||
|
if (format[index] == '%')
|
||||||
/* while there is room in buffer and format string is not empty */
|
|
||||||
while ((next_index < length) && (format[next_index] != '\0') &&
|
|
||||||
/* skip all flags and precision modifiers */
|
|
||||||
(((format[next_index] >= '0') && (format[next_index] <= '9')) ||
|
|
||||||
(format[next_index] == '-') ||
|
|
||||||
(format[next_index] == '+') ||
|
|
||||||
(format[next_index] == '#') ||
|
|
||||||
(format[next_index] == '.')))
|
|
||||||
{
|
{
|
||||||
/* skip to next character */
|
size_t next_index = index + 1;
|
||||||
next_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* look for length modifier, default to NONE */
|
/* while format string is not empty */
|
||||||
length_t length_modifier = LENGTH_NONE;
|
while ((format[next_index] != '\0') &&
|
||||||
|
/* skip all flags and precision modifiers */
|
||||||
/* look for two character length modifier */
|
(((format[next_index] >= '0') && (format[next_index] <= '9')) ||
|
||||||
if (format[next_index + 1] != '\0')
|
(format[next_index] == '-') ||
|
||||||
{
|
(format[next_index] == '+') ||
|
||||||
if ((format[next_index] == 'h') && (format[next_index + 1] == 'h'))
|
(format[next_index] == '#') ||
|
||||||
{
|
(format[next_index] == '.')))
|
||||||
length_modifier = LENGTH_HH;
|
|
||||||
}
|
|
||||||
else if ((format[next_index] == 'l') && (format[next_index + 1] == 'l'))
|
|
||||||
{
|
|
||||||
length_modifier = LENGTH_LL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* increment next_index if length modifier was found */
|
|
||||||
if (length_modifier != LENGTH_NONE)
|
|
||||||
{
|
|
||||||
next_index += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* look for one character length modifier if two character search failed */
|
|
||||||
if ((length_modifier == LENGTH_NONE) && (format[next_index] != '\0'))
|
|
||||||
{
|
|
||||||
if (format[next_index] == 'h')
|
|
||||||
{
|
|
||||||
length_modifier = LENGTH_H;
|
|
||||||
}
|
|
||||||
else if (format[next_index] == 'l')
|
|
||||||
{
|
|
||||||
length_modifier = LENGTH_L;
|
|
||||||
}
|
|
||||||
else if (format[next_index] == 'j')
|
|
||||||
{
|
|
||||||
length_modifier = LENGTH_J;
|
|
||||||
}
|
|
||||||
else if (format[next_index] == 'z')
|
|
||||||
{
|
|
||||||
length_modifier = LENGTH_Z;
|
|
||||||
}
|
|
||||||
else if (format[next_index] == 't')
|
|
||||||
{
|
|
||||||
length_modifier = LENGTH_T;
|
|
||||||
}
|
|
||||||
else if (format[next_index] == 'L')
|
|
||||||
{
|
|
||||||
length_modifier = LENGTH_CAPITAL_L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* increment next_index if length modifier was found */
|
|
||||||
if (length_modifier != LENGTH_NONE)
|
|
||||||
{
|
{
|
||||||
|
/* skip to next character */
|
||||||
next_index++;
|
next_index++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* read out character - this is a supported format character, '\0', or a not suported character */
|
/* look for length modifier, default to NONE */
|
||||||
char next = format[next_index];
|
length_t length_modifier = LENGTH_NONE;
|
||||||
|
|
||||||
/* signed integer */
|
/* look for two character length modifier */
|
||||||
if ((next == 'd') || (next == 'i'))
|
if (format[next_index + 1] != '\0')
|
||||||
{
|
|
||||||
MBED_SIGNED_STORAGE value = 0;
|
|
||||||
|
|
||||||
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
|
||||||
/* if 64 bit is enabled and the integer types are larger than the native type */
|
|
||||||
if (((length_modifier == LENGTH_LL) && (sizeof(long long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
|
|
||||||
((length_modifier == LENGTH_L) && (sizeof(long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
|
|
||||||
((length_modifier == LENGTH_NONE) && (sizeof(int) > sizeof(MBED_SIGNED_NATIVE_TYPE))))
|
|
||||||
{
|
{
|
||||||
/* use 64 bit storage type for readout */
|
if ((format[next_index] == 'h') && (format[next_index + 1] == 'h'))
|
||||||
value = va_arg(arguments, MBED_SIGNED_STORAGE);
|
{
|
||||||
}
|
length_modifier = LENGTH_HH;
|
||||||
else
|
}
|
||||||
#endif
|
else if ((format[next_index] == 'l') && (format[next_index + 1] == 'l'))
|
||||||
{
|
{
|
||||||
/* use native storage type (which can be 32 or 64 bit) */
|
length_modifier = LENGTH_LL;
|
||||||
value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
|
}
|
||||||
|
|
||||||
|
/* increment next_index if length modifier was found */
|
||||||
|
if (length_modifier != LENGTH_NONE)
|
||||||
|
{
|
||||||
|
next_index += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* constrict value based on lenght modifier */
|
/* look for one character length modifier if two character search failed */
|
||||||
switch (length_modifier)
|
if ((length_modifier == LENGTH_NONE) && (format[next_index] != '\0'))
|
||||||
{
|
{
|
||||||
case LENGTH_NONE:
|
if (format[next_index] == 'h')
|
||||||
value = (int) value;
|
{
|
||||||
break;
|
length_modifier = LENGTH_H;
|
||||||
case LENGTH_HH:
|
}
|
||||||
value = (signed char) value;
|
else if (format[next_index] == 'l')
|
||||||
break;
|
{
|
||||||
case LENGTH_H:
|
length_modifier = LENGTH_L;
|
||||||
value = (short int) value;
|
}
|
||||||
break;
|
else if (format[next_index] == 'j')
|
||||||
case LENGTH_L:
|
{
|
||||||
value = (long int) value;
|
length_modifier = LENGTH_J;
|
||||||
break;
|
}
|
||||||
case LENGTH_LL:
|
else if (format[next_index] == 'z')
|
||||||
value = (long long int) value;
|
{
|
||||||
break;
|
length_modifier = LENGTH_Z;
|
||||||
case LENGTH_J:
|
}
|
||||||
value = (intmax_t) value;
|
else if (format[next_index] == 't')
|
||||||
break;
|
{
|
||||||
case LENGTH_T:
|
length_modifier = LENGTH_T;
|
||||||
value = (ptrdiff_t) value;
|
}
|
||||||
break;
|
else if (format[next_index] == 'L')
|
||||||
default:
|
{
|
||||||
break;
|
length_modifier = LENGTH_CAPITAL_L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment next_index if length modifier was found */
|
||||||
|
if (length_modifier != LENGTH_NONE)
|
||||||
|
{
|
||||||
|
next_index++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index = next_index;
|
/* read out character - this is a supported format character, '\0', or a not suported character */
|
||||||
|
char next = format[next_index];
|
||||||
|
|
||||||
mbed_minimal_formatted_string_signed(buffer, length, &result, value);
|
/* signed integer */
|
||||||
}
|
if ((next == 'd') || (next == 'i'))
|
||||||
/* unsigned integer */
|
|
||||||
else if ((next == 'u') || (next == 'x') || (next == 'X'))
|
|
||||||
{
|
|
||||||
MBED_UNSIGNED_STORAGE value = 0;
|
|
||||||
|
|
||||||
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
|
||||||
/* if 64 bit is enabled and the integer types are larger than the native type */
|
|
||||||
if (((length_modifier == LENGTH_LL) && (sizeof(unsigned long long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
|
|
||||||
((length_modifier == LENGTH_L) && (sizeof(unsigned long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
|
|
||||||
((length_modifier == LENGTH_NONE) && (sizeof(unsigned int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))))
|
|
||||||
{
|
{
|
||||||
/* use 64 bit storage type for readout */
|
MBED_SIGNED_STORAGE value = 0;
|
||||||
value = va_arg(arguments, MBED_UNSIGNED_STORAGE);
|
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
||||||
|
/* if 64 bit is enabled and the integer types are larger than the native type */
|
||||||
|
if (((length_modifier == LENGTH_LL) && (sizeof(long long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_L) && (sizeof(long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_NONE) && (sizeof(int) > sizeof(MBED_SIGNED_NATIVE_TYPE))))
|
||||||
|
{
|
||||||
|
/* use 64 bit storage type for readout */
|
||||||
|
value = va_arg(arguments, MBED_SIGNED_STORAGE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* use native storage type (which can be 32 or 64 bit) */
|
||||||
|
value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constrict value based on lenght modifier */
|
||||||
|
switch (length_modifier)
|
||||||
|
{
|
||||||
|
case LENGTH_NONE:
|
||||||
|
value = (int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_HH:
|
||||||
|
value = (signed char) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_H:
|
||||||
|
value = (short int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_L:
|
||||||
|
value = (long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_LL:
|
||||||
|
value = (long long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_J:
|
||||||
|
value = (intmax_t) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_T:
|
||||||
|
value = (ptrdiff_t) value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_signed(buffer, length, &result, value);
|
||||||
}
|
}
|
||||||
else
|
/* unsigned integer */
|
||||||
#endif
|
else if ((next == 'u') || (next == 'x') || (next == 'X'))
|
||||||
{
|
{
|
||||||
/* use native storage type (which can be 32 or 64 bit) */
|
MBED_UNSIGNED_STORAGE value = 0;
|
||||||
value = va_arg(arguments, MBED_UNSIGNED_NATIVE_TYPE);
|
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
||||||
|
/* if 64 bit is enabled and the integer types are larger than the native type */
|
||||||
|
if (((length_modifier == LENGTH_LL) && (sizeof(unsigned long long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_L) && (sizeof(unsigned long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
|
||||||
|
((length_modifier == LENGTH_NONE) && (sizeof(unsigned int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))))
|
||||||
|
{
|
||||||
|
/* use 64 bit storage type for readout */
|
||||||
|
value = va_arg(arguments, MBED_UNSIGNED_STORAGE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* use native storage type (which can be 32 or 64 bit) */
|
||||||
|
value = va_arg(arguments, MBED_UNSIGNED_NATIVE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constrict value based on lenght modifier */
|
||||||
|
switch (length_modifier)
|
||||||
|
{
|
||||||
|
case LENGTH_NONE:
|
||||||
|
value = (unsigned int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_HH:
|
||||||
|
value = (unsigned char) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_H:
|
||||||
|
value = (unsigned short int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_L:
|
||||||
|
value = (unsigned long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_LL:
|
||||||
|
value = (unsigned long long int) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_J:
|
||||||
|
value = (uintmax_t) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_Z:
|
||||||
|
value = (size_t) value;
|
||||||
|
break;
|
||||||
|
case LENGTH_T:
|
||||||
|
value = (ptrdiff_t) value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
/* write unsigned or hexadecimal */
|
||||||
|
if (next == 'u')
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_unsigned(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
|
||||||
/* constrict value based on lenght modifier */
|
/* treat all floating points the same */
|
||||||
switch (length_modifier)
|
else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G'))
|
||||||
{
|
{
|
||||||
case LENGTH_NONE:
|
double value = va_arg(arguments, double);
|
||||||
value = (unsigned int) value;
|
index = next_index;
|
||||||
break;
|
|
||||||
case LENGTH_HH:
|
mbed_minimal_formatted_string_double(buffer, length, &result, value);
|
||||||
value = (unsigned char) value;
|
|
||||||
break;
|
|
||||||
case LENGTH_H:
|
|
||||||
value = (unsigned short int) value;
|
|
||||||
break;
|
|
||||||
case LENGTH_L:
|
|
||||||
value = (unsigned long int) value;
|
|
||||||
break;
|
|
||||||
case LENGTH_LL:
|
|
||||||
value = (unsigned long long int) value;
|
|
||||||
break;
|
|
||||||
case LENGTH_J:
|
|
||||||
value = (uintmax_t) value;
|
|
||||||
break;
|
|
||||||
case LENGTH_Z:
|
|
||||||
value = (size_t) value;
|
|
||||||
break;
|
|
||||||
case LENGTH_T:
|
|
||||||
value = (ptrdiff_t) value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
index = next_index;
|
/* character */
|
||||||
|
else if (next == 'c')
|
||||||
/* write unsigned or hexadecimal */
|
|
||||||
if (next == 'u')
|
|
||||||
{
|
{
|
||||||
mbed_minimal_formatted_string_unsigned(buffer, length, &result, value);
|
char value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
/* string */
|
||||||
|
else if (next == 's')
|
||||||
|
{
|
||||||
|
char* value = va_arg(arguments, char*);
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_string(buffer, length, &result, value);
|
||||||
|
}
|
||||||
|
/* pointer */
|
||||||
|
else if (next == 'p')
|
||||||
|
{
|
||||||
|
void* value = va_arg(arguments, void*);
|
||||||
|
index = next_index;
|
||||||
|
|
||||||
|
mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value);
|
/* write all characters between format beginning and unrecognied modifier */
|
||||||
|
while (index < next_index)
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if this is not the end of the string, write unrecognized modifier */
|
||||||
|
if (next != '\0')
|
||||||
|
{
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* break out of for loop */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
|
|
||||||
/* treat all floating points the same */
|
|
||||||
else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G'))
|
|
||||||
{
|
|
||||||
double value = va_arg(arguments, double);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_double(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* character */
|
|
||||||
else if (next == 'c')
|
|
||||||
{
|
|
||||||
char value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
/* string */
|
|
||||||
else if (next == 's')
|
|
||||||
{
|
|
||||||
char* value = va_arg(arguments, char*);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_string(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
/* pointer */
|
|
||||||
else if (next == 'p')
|
|
||||||
{
|
|
||||||
void* value = va_arg(arguments, void*);
|
|
||||||
index = next_index;
|
|
||||||
|
|
||||||
mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
/* not a format specifier */
|
||||||
{
|
{
|
||||||
/* write all characters between format beginning and unrecognied modifier */
|
/* write normal character */
|
||||||
while (index < next_index)
|
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
||||||
{
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if this is not the end of the string, write unrecognized modifier */
|
|
||||||
if (next != '\0')
|
|
||||||
{
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* break out of for loop */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
/* not a format specifier */
|
|
||||||
{
|
|
||||||
/* write normal character */
|
|
||||||
mbed_minimal_formatted_string_character(buffer, length, &result, format[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if writing to buffer, NULL terminate string in reserved space*/
|
/* if writing to buffer, NULL terminate string in reserved space*/
|
||||||
if (buffer)
|
if (buffer && ((size_t)result < length))
|
||||||
{
|
{
|
||||||
buffer[result] = '\0';
|
buffer[result] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue