Avoid calling strlen with BearSSL

This commit is contained in:
UnknownShadow200 2025-08-23 12:22:54 +10:00
parent 7bb3943467
commit a3e54ebcf3
8 changed files with 196 additions and 167 deletions

View File

@ -1,131 +1,36 @@
#include "Core.h"
#ifndef CC_BUILD_WEB
#if defined CC_BUILD_WEB
/* Implemented in web http backend without C worker thread(s) */
#elif !defined CC_BUILD_NETWORKING
#include "Http.h"
#include "Game.h"
void HttpRequest_Free(struct HttpRequest* request) { }
cc_bool Http_GetResult(int reqID, struct HttpRequest* item) {
return false;
}
int Http_AsyncGetSkin(const cc_string* skinName, cc_uint8 flags) {
return -1;
}
int Http_CheckProgress(int reqID) {
return -1;
}
void Http_LogError(const char* action, const struct HttpRequest* item) {
}
static void Http_NullInit(void) { }
struct IGameComponent Http_Component = {
Http_NullInit
};
#else
#include "_HttpBase.h"
/* Ensures data buffer has enough space left to append amount bytes */
static cc_bool Http_BufferExpand(struct HttpRequest* req, cc_uint32 amount) {
cc_uint32 newSize = req->size + amount;
cc_uint8* ptr;
if (newSize <= req->_capacity) return true;
if (!req->_capacity) {
/* Allocate initial storage */
req->_capacity = req->contentLength ? req->contentLength : 1;
req->_capacity = max(req->_capacity, newSize);
ptr = (cc_uint8*)Mem_TryAlloc(req->_capacity, 1);
} else {
/* Reallocate if capacity reached */
req->_capacity = newSize;
ptr = (cc_uint8*)Mem_TryRealloc(req->data, newSize, 1);
}
if (!ptr) return false;
req->data = ptr;
return true;
}
/* Increases size and updates current progress */
static void Http_BufferExpanded(struct HttpRequest* req, cc_uint32 read) {
req->size += read;
if (req->contentLength) req->progress = (int)(100.0f * req->size / req->contentLength);
}
/*########################################################################################################################*
*---------------------------------------------------Common backend code---------------------------------------------------*
*#########################################################################################################################*/
static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) {
cc_string name, data;
int dataEnd;
String_UNSAFE_Separate(value, '=', &name, &data);
/* Cookie is: __cfduid=xyz; expires=abc; path=/; domain=.classicube.net; HttpOnly */
/* However only the __cfduid=xyz part of the cookie should be stored */
dataEnd = String_IndexOf(&data, ';');
if (dataEnd >= 0) data.length = dataEnd;
EntryList_Set(req->cookies, &name, &data, '=');
}
static void Http_ParseContentLength(struct HttpRequest* req, const cc_string* value) {
int contentLen = 0;
Convert_ParseInt(value, &contentLen);
if (contentLen <= 0) return;
req->contentLength = contentLen;
}
/* Parses a HTTP header */
static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) {
static const cc_string httpVersion = String_FromConst("HTTP");
cc_string name, value, parts[3];
int numParts;
/* HTTP[version] [status code] [status reason] */
if (String_CaselessStarts(line, &httpVersion)) {
numParts = String_UNSAFE_Split(line, ' ', parts, 3);
if (numParts >= 2) Convert_ParseInt(&parts[1], &req->statusCode);
}
/* For all other headers: name: value */
if (!String_UNSAFE_Separate(line, ':', &name, &value)) return;
if (String_CaselessEqualsConst(&name, "ETag")) {
String_CopyToRawArray(req->etag, &value);
} else if (String_CaselessEqualsConst(&name, "Content-Length")) {
Http_ParseContentLength(req, &value);
} else if (String_CaselessEqualsConst(&name, "X-Dropbox-Content-Length")) {
/* dropbox stopped returning Content-Length header since switching to chunked transfer */
/* https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Dropbox-media-can-t-be-access-by-azure-blob/td-p/575458 */
Http_ParseContentLength(req, &value);
} else if (String_CaselessEqualsConst(&name, "Last-Modified")) {
String_CopyToRawArray(req->lastModified, &value);
} else if (req->cookies && String_CaselessEqualsConst(&name, "Set-Cookie")) {
Http_ParseCookie(req, &value);
}
}
/* Adds a http header to the request headers. */
static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value);
/* Adds all the appropriate headers for a request. */
static void Http_SetRequestHeaders(struct HttpRequest* req) {
static const cc_string contentType = String_FromConst("application/x-www-form-urlencoded");
cc_string str, cookies; char cookiesBuffer[1024];
int i;
if (req->lastModified[0]) {
str = String_FromRawArray(req->lastModified);
Http_AddHeader(req, "If-Modified-Since", &str);
}
if (req->etag[0]) {
str = String_FromRawArray(req->etag);
Http_AddHeader(req, "If-None-Match", &str);
}
if (req->data) Http_AddHeader(req, "Content-Type", &contentType);
if (!req->cookies || !req->cookies->count) return;
String_InitArray(cookies, cookiesBuffer);
for (i = 0; i < req->cookies->count; i++) {
if (i) String_AppendConst(&cookies, "; ");
str = StringsBuffer_UNSAFE_Get(req->cookies, i);
String_AppendString(&cookies, &str);
}
Http_AddHeader(req, "Cookie", &cookies);
}
/* TODO: Rewrite to use a local variable instead */
static cc_string* Http_GetUserAgent_UNSAFE(void) {
static char userAgentBuffer[STRING_SIZE];
static cc_string userAgent;
String_InitArray(userAgent, userAgentBuffer);
String_AppendConst(&userAgent, GAME_APP_NAME);
String_AppendConst(&userAgent, Platform_AppNameSuffix);
return &userAgent;
}
#if CC_NET_BACKEND == CC_NET_BACKEND_BUILTIN
#include "Errors.h"
#include "PackedCol.h"
@ -737,24 +642,6 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* urlStr) {
static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) {
return SSLBackend_DescribeError(res, dst);
}
#elif !defined CC_BUILD_NETWORKING
/*########################################################################################################################*
*------------------------------------------------------Null backend-------------------------------------------------------*
*#########################################################################################################################*/
#include "Errors.h"
static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) {
return false;
}
static void HttpBackend_Init(void) { }
static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value) { }
static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) {
req->progress = 100;
return ERR_NOT_SUPPORTED;
}
#endif

View File

@ -578,6 +578,7 @@ static cc_result ExtractFrom(struct Stream* stream, const cc_string* path) {
}
#if defined CC_BUILD_PS1 || defined CC_BUILD_SATURN
/* Load hardcoded texture pack */
#include "../misc/ps1/classicubezip.h"
static cc_result ExtractFromFile(const cc_string* path) {
@ -586,6 +587,11 @@ static cc_result ExtractFromFile(const cc_string* path) {
return ExtractFrom(&stream, path);
}
#elif !defined CC_BUILD_FILESYSTEM
/* E.g. GBA/32X don't support textures at all */
static cc_result ExtractFromFile(const cc_string* path) {
return ERR_NOT_SUPPORTED;
}
#else
static cc_result ExtractFromFile(const cc_string* path) {
struct Stream stream;

View File

@ -23,14 +23,11 @@ void HttpRequest_Free(struct HttpRequest* request) {
}
#define HttpRequest_Copy(dst, src) Mem_Copy(dst, src, sizeof(struct HttpRequest))
/*########################################################################################################################*
*----------------------------------------------------Http requests list---------------------------------------------------*
*#########################################################################################################################*/
#ifdef CC_BUILD_NETWORKING
#define HTTP_DEF_ELEMS 10
#else
#define HTTP_DEF_ELEMS 1 /* TODO better unused code removal */
#endif
struct RequestList {
int count, capacity;
@ -111,6 +108,133 @@ static void RequestList_Free(struct RequestList* list) {
}
/*########################################################################################################################*
*---------------------------------------------------Common buffer code----------------------------------------------------*
*#########################################################################################################################*/
/* Ensures data buffer has enough space left to append amount bytes */
static cc_bool Http_BufferExpand(struct HttpRequest* req, cc_uint32 amount) {
cc_uint32 newSize = req->size + amount;
cc_uint8* ptr;
if (newSize <= req->_capacity) return true;
if (!req->_capacity) {
/* Allocate initial storage */
req->_capacity = req->contentLength ? req->contentLength : 1;
req->_capacity = max(req->_capacity, newSize);
ptr = (cc_uint8*)Mem_TryAlloc(req->_capacity, 1);
} else {
/* Reallocate if capacity reached */
req->_capacity = newSize;
ptr = (cc_uint8*)Mem_TryRealloc(req->data, newSize, 1);
}
if (!ptr) return false;
req->data = ptr;
return true;
}
/* Increases size and updates current progress */
static void Http_BufferExpanded(struct HttpRequest* req, cc_uint32 read) {
req->size += read;
if (req->contentLength) req->progress = (int)(100.0f * req->size / req->contentLength);
}
/*########################################################################################################################*
*---------------------------------------------------Common header code----------------------------------------------------*
*#########################################################################################################################*/
static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) {
cc_string name, data;
int dataEnd;
String_UNSAFE_Separate(value, '=', &name, &data);
/* Cookie is: __cfduid=xyz; expires=abc; path=/; domain=.classicube.net; HttpOnly */
/* However only the __cfduid=xyz part of the cookie should be stored */
dataEnd = String_IndexOf(&data, ';');
if (dataEnd >= 0) data.length = dataEnd;
EntryList_Set(req->cookies, &name, &data, '=');
}
static void Http_ParseContentLength(struct HttpRequest* req, const cc_string* value) {
int contentLen = 0;
Convert_ParseInt(value, &contentLen);
if (contentLen <= 0) return;
req->contentLength = contentLen;
}
/* Parses a HTTP header */
static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) {
static const cc_string httpVersion = String_FromConst("HTTP");
cc_string name, value, parts[3];
int numParts;
/* HTTP[version] [status code] [status reason] */
if (String_CaselessStarts(line, &httpVersion)) {
numParts = String_UNSAFE_Split(line, ' ', parts, 3);
if (numParts >= 2) Convert_ParseInt(&parts[1], &req->statusCode);
}
/* For all other headers: name: value */
if (!String_UNSAFE_Separate(line, ':', &name, &value)) return;
if (String_CaselessEqualsConst(&name, "ETag")) {
String_CopyToRawArray(req->etag, &value);
} else if (String_CaselessEqualsConst(&name, "Content-Length")) {
Http_ParseContentLength(req, &value);
} else if (String_CaselessEqualsConst(&name, "X-Dropbox-Content-Length")) {
/* dropbox stopped returning Content-Length header since switching to chunked transfer */
/* https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Dropbox-media-can-t-be-access-by-azure-blob/td-p/575458 */
Http_ParseContentLength(req, &value);
} else if (String_CaselessEqualsConst(&name, "Last-Modified")) {
String_CopyToRawArray(req->lastModified, &value);
} else if (req->cookies && String_CaselessEqualsConst(&name, "Set-Cookie")) {
Http_ParseCookie(req, &value);
}
}
/* Adds a http header to the request headers. */
static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value);
/* Adds all the appropriate headers for a request. */
static void Http_SetRequestHeaders(struct HttpRequest* req) {
static const cc_string contentType = String_FromConst("application/x-www-form-urlencoded");
cc_string str, cookies; char cookiesBuffer[1024];
int i;
if (req->lastModified[0]) {
str = String_FromRawArray(req->lastModified);
Http_AddHeader(req, "If-Modified-Since", &str);
}
if (req->etag[0]) {
str = String_FromRawArray(req->etag);
Http_AddHeader(req, "If-None-Match", &str);
}
if (req->data) Http_AddHeader(req, "Content-Type", &contentType);
if (!req->cookies || !req->cookies->count) return;
String_InitArray(cookies, cookiesBuffer);
for (i = 0; i < req->cookies->count; i++) {
if (i) String_AppendConst(&cookies, "; ");
str = StringsBuffer_UNSAFE_Get(req->cookies, i);
String_AppendString(&cookies, &str);
}
Http_AddHeader(req, "Cookie", &cookies);
}
/* TODO: Rewrite to use a local variable instead */
static cc_string* Http_GetUserAgent_UNSAFE(void) {
static char userAgentBuffer[STRING_SIZE];
static cc_string userAgent;
String_InitArray(userAgent, userAgentBuffer);
String_AppendConst(&userAgent, GAME_APP_NAME);
String_AppendConst(&userAgent, Platform_AppNameSuffix);
return &userAgent;
}
/*########################################################################################################################*
*--------------------------------------------------Common downloader code-------------------------------------------------*
*#########################################################################################################################*/

View File

@ -33,18 +33,6 @@
* autodetection applies.
*/
/* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */
#ifdef NXDK
#define BR_AES_X86NI 0
#define BR_ENABLE_INTRINSICS 0
#define BR_SSE2 0
#endif
/* intrin.h doesn't exist in older TinyC */
#if defined __TINYC__
#define BR_INT128 0
#endif
/*
* When BR_64 is enabled, 64-bit integer types are assumed to be
* efficient (i.e. the architecture has 64-bit registers and can

View File

@ -35,6 +35,30 @@
#include "config.h"
#include "bearssl.h"
/* ==== BEG ClassiCube specific ==== */
static size_t br_strlen(const char* a) {
int i = 0;
while (*a++) i++;
return i;
}
#define br_memcpy memcpy
#define br_memset memset
#define br_memmove memmove
/* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */
#ifdef NXDK
#define BR_AES_X86NI 0
#define BR_ENABLE_INTRINSICS 0
#define BR_SSE2 0
#endif
/* intrin.h doesn't exist in older TinyC */
#if defined __TINYC__
#define BR_INT128 0
#endif
/* ==== END ClassiCube specific ==== */
/*
* On MSVC, disable the warning about applying unary minus on an
* unsigned type: it is standard, we do it all the time, and for

View File

@ -64,7 +64,7 @@ br_ssl_client_reset(br_ssl_client_context *cc,
if (server_name == NULL) {
cc->eng.server_name[0] = 0;
} else {
n = strlen(server_name) + 1;
n = br_strlen(server_name) + 1;
if (n > sizeof cc->eng.server_name) {
br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM);
return 0;

View File

@ -1246,7 +1246,7 @@ br_ssl_hs_client_run(void *t0ctx)
/* copy-protocol-name */
size_t idx = T0_POP();
size_t len = strlen(ENG->protocol_names[idx]);
size_t len = br_strlen(ENG->protocol_names[idx]);
memcpy(ENG->pad, ENG->protocol_names[idx], len);
T0_PUSH(len);
@ -1346,7 +1346,7 @@ br_ssl_hs_client_run(void *t0ctx)
}
len = 6;
for (u = 0; u < ENG->protocol_names_num; u ++) {
len += 1 + strlen(ENG->protocol_names[u]);
len += 1 + br_strlen(ENG->protocol_names[u]);
}
T0_PUSH(len);
@ -1591,10 +1591,10 @@ br_ssl_hs_client_run(void *t0ctx)
}
break;
case 63: {
/* strlen */
/* br_strlen */
void *str = (unsigned char *)ENG + (size_t)T0_POP();
T0_PUSH((uint32_t)strlen(str));
T0_PUSH((uint32_t)br_strlen(str));
}
break;
@ -1766,7 +1766,7 @@ br_ssl_hs_client_run(void *t0ctx)
const char *name;
name = ENG->protocol_names[u];
if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) {
if (len == br_strlen(name) && memcmp(ENG->pad, name, len) == 0) {
T0_PUSH(u);
T0_RET();
}

View File

@ -1440,7 +1440,7 @@ br_x509_minimal_run(void *t0ctx)
T0_PUSH(0);
T0_RET();
}
n1 = strlen(CTX->server_name);
n1 = br_strlen(CTX->server_name);
n2 = CTX->pad[0];
if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) {
T0_PUSHi(-1);