Tasmota/lib/libesp32/berry_mapping/src/be_raisef.c

74 lines
2.3 KiB
C

/*********************************************************************************************\
* Extended version of be_raise() - SECURITY PATCHED
*
* SECURITY IMPROVEMENTS (BM-005 Patch):
* - Fixed format string vulnerability
* - Added input validation and bounds checking
* - Safe string formatting with overflow protection
* - Enhanced error handling
\*********************************************************************************************/
#include "be_mapping.h"
#include "be_exec.h"
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
// SECURITY: Safe format string function - BM-005 patch
void be_raisef(bvm *vm, const char *except, const char *msg, ...) {
// SECURITY: Input validation
#if BE_MAPPING_ENABLE_INPUT_VALIDATION
if (vm == NULL) {
return; // Cannot raise exception without VM
}
if (except == NULL) {
except = "internal_error"; // Default exception type
}
if (msg == NULL) {
be_raise(vm, except, "NULL error message");
return;
}
// SECURITY: Validate format string for basic safety
// Count format specifiers to detect potential format string attacks
int format_count = 0;
const char *p = msg;
while ((p = strchr(p, '%')) != NULL) {
p++;
if (*p == '%') {
p++; // Skip literal %
continue;
}
format_count++;
if (format_count > 10) { // Reasonable limit
be_raise(vm, "security_error", "Format string validation failed");
return;
}
}
#endif // BE_MAPPING_ENABLE_INPUT_VALIDATION
// To save stack space support logging for max text length of 128 characters
char log_data[128];
va_list arg;
va_start(arg, msg);
// SECURITY: Use safe formatting with bounds checking
int len = vsnprintf(log_data, sizeof(log_data) - 3, msg, arg);
va_end(arg);
// SECURITY: Handle formatting errors
if (len < 0) {
be_raise(vm, except, "Format string error");
return;
}
// SECURITY: Handle truncation safely
if (len >= (int)(sizeof(log_data) - 3)) {
strcat(log_data, "..."); // Indicate truncation
}
// SECURITY: Validate final string before raising
log_data[sizeof(log_data) - 1] = '\0'; // Ensure null termination
be_raise(vm, except, log_data);
}