From 38d1620529866dbf638c6fd8a3e8e438b3c6a43c Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Mon, 26 Aug 2024 01:10:16 +0200 Subject: Avoid searching for boundary in file content Making the boundary string very unlikely to collide with the file to upload allows Dillo to assume it would never be found and avoids the expensive memmem() check. Even if major implementations tend to add several '-' characters to multipart/form-data boundaries, this is not enforced by RFC 2046, so it can be increase to 70 random characters. See: https://lists.mailman3.com/hyperkitty/list/dillo-dev@mailman3.com/thread/VUB5PIOPJZ2VTCVGQPBZMGOYEISTXCFX/ --- src/dialog.cc | 1 + src/form.cc | 30 ++++++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/dialog.cc b/src/dialog.cc index ac007315..0137472b 100644 --- a/src/dialog.cc +++ b/src/dialog.cc @@ -14,6 +14,7 @@ */ #include // for rint() +#include #include #include diff --git a/src/form.cc b/src/form.cc index 93bd4864..6e81edf6 100644 --- a/src/form.cc +++ b/src/form.cc @@ -1246,6 +1246,24 @@ Dstr *DilloHtmlForm::buildQueryData(DilloHtmlInput *active_submit) return DataStr; } +static void generate_boundary(Dstr *boundary) +{ + for (int i = 0; i < 70; i++) { + /* Extracted from RFC 2046, section 5.1.1. */ + static const char set[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "'()+_,-./:=? "; + char s[sizeof " "] = {0}; + + do { + *s = rand(); + } while (!strspn(s, set)); + + dStr_append(boundary, s); + } +} + /** * Generate a boundary string for use in separating the parts of a * multipart/form-data submission. @@ -1253,7 +1271,6 @@ Dstr *DilloHtmlForm::buildQueryData(DilloHtmlInput *active_submit) char *DilloHtmlForm::makeMultipartBoundary(iconv_t char_encoder, DilloHtmlInput *active_submit) { - const int max_tries = 10; Dlist *values = dList_new(5); Dstr *DataStr = dStr_new(""); Dstr *boundary = dStr_new(""); @@ -1294,15 +1311,8 @@ char *DilloHtmlForm::makeMultipartBoundary(iconv_t char_encoder, } } - /* generate a boundary that is not contained within the data */ - for (int i = 0; i < max_tries && !ret; i++) { - // Firefox-style boundary - dStr_sprintf(boundary, "---------------------------%d%d%d", - rand(), rand(), rand()); - dStr_truncate(boundary, 70); - if (dStr_memmem(DataStr, boundary) == NULL) - ret = boundary->str; - } + generate_boundary(boundary); + ret = boundary->str; dList_free(values); dStr_free(DataStr, 1); dStr_free(boundary, (ret == NULL)); -- cgit v1.2.3