safe string

This commit is contained in:
sfja 2025-03-19 21:11:10 +01:00
parent 0cbf4ca647
commit 1434772b35
4 changed files with 72 additions and 18 deletions

View File

@ -101,7 +101,6 @@ void route_get_receipts_all(HttpCtx* ctx)
String receipts_str; String receipts_str;
string_construct(&receipts_str); string_construct(&receipts_str);
string_push_str(&receipts_str, "");
for (size_t i = 0; i < receipts.size; ++i) { for (size_t i = 0; i < receipts.size; ++i) {
if (i != 0) { if (i != 0) {
string_pushf(&receipts_str, ","); string_pushf(&receipts_str, ",");

View File

@ -52,27 +52,64 @@ StrSlice str_split_next(StrSplitter* splitter)
return slice; return slice;
} }
void string_push_str(String* string, const char* str) int string_construct(String* string)
{ {
for (size_t i = 0; i < strlen(str); ++i) { int res = string_data_construct(string);
string_data_push(string, str[i]); if (res != 0) {
return res;
} }
// NOTE: Vec is assumed to be initialized with atleast 1 allocated byte.
string_data_push(string, '\0'); string->data[0] = '\0';
string->size -= 1; return 0;
} }
void string_push_fmt_va(String* string, const char* fmt, ...) void string_destroy(String* string)
{
string_data_destroy(string);
}
int string_push(String* string, char value)
{
int res = string_data_push(string, value);
if (res != 0)
return res;
res = string_data_push(string, '\0');
if (res != 0)
return res;
string->size -= 1;
return 0;
}
int string_push_str(String* string, const char* str)
{
for (size_t i = 0; i < strlen(str); ++i) {
int res = string_data_push(string, str[i]);
if (res != 0)
return res;
}
int res = string_data_push(string, '\0');
if (res != 0)
return res;
string->size -= 1;
return 0;
}
int string_push_fmt_va(String* string, const char* fmt, ...)
{ {
va_list args1; va_list args1;
va_start(args1, fmt); va_start(args1, fmt);
va_list args2; va_list args2;
va_copy(args2, args1); va_copy(args2, args1);
char buf[1 + vsnprintf(NULL, 0, fmt, args1)];
size_t buffer_size = (size_t)vsnprintf(NULL, 0, fmt, args1) + 1;
char* buf = malloc(buffer_size);
va_end(args1); va_end(args1);
vsnprintf(buf, sizeof buf, fmt, args2);
vsnprintf(buf, buffer_size, fmt, args2);
va_end(args2); va_end(args2);
string_push_str(string, buf);
return string_push_str(string, buf);
} }
char* string_copy(const String* string) char* string_copy(const String* string)

View File

@ -27,8 +27,11 @@ StrSlice str_split_next(StrSplitter* splitter);
DEFINE_VEC(char, String, string_data) DEFINE_VEC(char, String, string_data)
void string_push_str(String* string, const char* str); int string_construct(String* string);
void string_push_fmt_va(String* string, const char* fmt, ...); void string_destroy(String* string);
int string_push(String* string, char value);
int string_push_str(String* string, const char* str);
int string_push_fmt_va(String* string, const char* fmt, ...);
char* string_copy(const String* string); char* string_copy(const String* string);
#define string_pushf(STRING, ...) string_push_fmt_va(STRING, __VA_ARGS__) #define string_pushf(STRING, ...) string_push_fmt_va(STRING, __VA_ARGS__)

View File

@ -45,7 +45,7 @@ Deno.test("test backend", async (t) => {
{ "Session-Token": token! }, { "Session-Token": token! },
); );
// console.log(sessionUserRes.user); //console.log(sessionUserRes.user);
assertEquals(sessionUserRes.ok, true); assertEquals(sessionUserRes.ok, true);
}); });
@ -58,7 +58,7 @@ Deno.test("test backend", async (t) => {
{ "Session-Token": token! }, { "Session-Token": token! },
); );
// console.log(sessionUserRes); //console.log(sessionUserRes);
assertEquals(sessionUserRes.ok, true); assertEquals(sessionUserRes.ok, true);
}); });
@ -81,6 +81,20 @@ Deno.test("test backend", async (t) => {
async function testCartsAndReceipts(t: Deno.TestContext, token: string) { async function testCartsAndReceipts(t: Deno.TestContext, token: string) {
let receiptId: number | undefined = undefined; let receiptId: number | undefined = undefined;
await t.step("test /api/receipts/all", async () => {
const res = await get<{
ok: boolean;
receipts: { timestamp: string }[];
}>(
`/api/receipts/all`,
{ "Session-Token": token },
);
// console.log(res);
assertEquals(res.ok, true);
assertEquals(res.receipts.length, 0);
});
const user1 = await sessionUser(token); const user1 = await sessionUser(token);
await t.step("test /api/carts/purchase", async () => { await t.step("test /api/carts/purchase", async () => {
@ -88,13 +102,14 @@ async function testCartsAndReceipts(t: Deno.TestContext, token: string) {
"/api/carts/purchase", "/api/carts/purchase",
{ {
items: [ items: [
{ product_id: 1, amount: 2 }, { product_id: 1, amount: 5 },
{ product_id: 2, amount: 5 }, { product_id: 2, amount: 2 },
], ],
}, },
{ "Session-Token": token }, { "Session-Token": token },
); );
//console.log(res);
assertEquals(res.ok, true); assertEquals(res.ok, true);
receiptId = res.receipt_id; receiptId = res.receipt_id;
}); });
@ -103,7 +118,7 @@ async function testCartsAndReceipts(t: Deno.TestContext, token: string) {
assertNotEquals(user1.balance_dkk_cent, user2.balance_dkk_cent); assertNotEquals(user1.balance_dkk_cent, user2.balance_dkk_cent);
assertEquals( assertEquals(
user1.balance_dkk_cent - user2.balance_dkk_cent, user1.balance_dkk_cent - user2.balance_dkk_cent,
1195 * 2 + 1295 * 5, 1195 * 5 + 1295 * 2,
); );
if (!receiptId) { if (!receiptId) {