Skip to content

Commit 83adab4

Browse files
authored
Fix pqus marshaling (#12490)
The pqus scheme marshaling logic used "strlen" which accidentally picked up LogAccess::strlen rather than the intended std strlen. This resulted in padded-counting rather than actual strlen counting, which threw off our buffer counting logic and led to corruption and/or crashing. The updated ip_allow.test.py reproduced a crash without the LogAccess.cc patch included in this commit. With the LogAccess patch, the test now reproduces the expected scheme. Function renames for clarity: * LogAccess::round_strlen is not a strlen at all. Rather it converts a given length to a padded length for alignment. * LogAccess::strlen returns the padded version of strlen. To make this explicit (and avoid potential accitantal clashes with ::strlen), I renamed this to padded_strlen. This also adds doxygen comments to explain these functions further.
1 parent 3a7fabd commit 83adab4

6 files changed

Lines changed: 81 additions & 77 deletions

File tree

include/proxy/logging/LogAccess.h

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,24 @@ class LogAccess
331331

332332
static int unmarshal_record(char **buf, char *dest, int len);
333333

334-
//
335-
// our own strlen function that pads strings to even int64_t boundaries
336-
// so that there are no alignment problems with the int values.
337-
//
338-
static int round_strlen(int len);
339-
static int strlen(const char *str);
334+
/** Find the padded length of a given value for alignment purposes.
335+
* @param[in] len The length from which to calculate the padded length.
336+
* @return The padded length on an even int64_t boundary.
337+
*/
338+
static int padded_length(int len);
339+
340+
/** strlen wrapped in @a padded_length for calculaing padded string lengths.
341+
*
342+
* This is our own version of strlen which takes into account nullptr input
343+
* for DEFAULT_STR and adds space for the null terminator. After accounting
344+
* for these, it passes the result to @a padded_length to ensure space for
345+
* alignment. This function is useful, for example, when calculating the
346+
* length for @a marshal_str.
347+
*
348+
* @param[in] str The string from which to calculate the padded length.
349+
* @return The padded length for the string on an even int64_t boundary.
350+
*/
351+
static int padded_strlen(const char *str);
340352

341353
public:
342354
static void marshal_int(char *dest, int64_t source);
@@ -386,25 +398,25 @@ class LogAccess
386398
};
387399

388400
inline int
389-
LogAccess::round_strlen(int len)
401+
LogAccess::padded_length(int len)
390402
{
391403
return INK_ALIGN_DEFAULT(len);
392404
}
393405

394406
/*-------------------------------------------------------------------------
395-
LogAccess::strlen
407+
LogAccess::padded_strlen
396408
397409
Take trailing null and alignment padding into account. This makes sure
398410
that strings in the LogBuffer are laid out properly.
399411
-------------------------------------------------------------------------*/
400412

401413
inline int
402-
LogAccess::strlen(const char *str)
414+
LogAccess::padded_strlen(const char *str)
403415
{
404416
if (str == nullptr || str[0] == 0) {
405-
return round_strlen(sizeof(DEFAULT_STR));
417+
return padded_length(sizeof(DEFAULT_STR));
406418
} else {
407-
return (int)(round_strlen(((int)::strlen(str) + 1))); // actual bytes for string
419+
return (int)(padded_length(((int)::strlen(str) + 1))); // actual bytes for string
408420
}
409421
}
410422

src/proxy/logging/LogAccess.cc

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ LogAccess::marshal_proxy_host_ip(char *buf)
161161
int
162162
LogAccess::marshal_process_uuid(char *buf)
163163
{
164-
int len = round_strlen(TS_UUID_STRING_LEN + 1);
164+
int len = padded_length(TS_UUID_STRING_LEN + 1);
165165

166166
if (buf) {
167167
const char *str = const_cast<char *>(Machine::instance()->process_uuid.getString());
@@ -211,7 +211,7 @@ LogAccess::marshal_config_str_var(char *config_var, char *buf)
211211
{
212212
auto str{RecGetRecordStringAlloc(config_var)};
213213
auto c_str{ats_as_c_str(str)};
214-
int len = LogAccess::strlen(c_str);
214+
int len = LogAccess::padded_strlen(c_str);
215215
if (buf) {
216216
marshal_str(buf, c_str, len);
217217
}
@@ -768,7 +768,7 @@ unmarshal_str_json(char **buf, char *dest, int len, LogSlice *slice)
768768
int val_len = static_cast<int>(::strlen(val_buf));
769769
int escaped_len = escape_json(nullptr, val_buf, val_len);
770770

771-
*buf += LogAccess::strlen(val_buf); // this is how it was stored
771+
*buf += LogAccess::padded_strlen(val_buf); // this is how it was stored
772772

773773
if (slice && slice->m_enable) {
774774
int offset, n;
@@ -820,7 +820,7 @@ LogAccess::unmarshal_str(char **buf, char *dest, int len, LogSlice *slice, LogEs
820820
char *val_buf = *buf;
821821
int val_len = static_cast<int>(::strlen(val_buf));
822822

823-
*buf += LogAccess::strlen(val_buf); // this is how it was stored
823+
*buf += LogAccess::padded_strlen(val_buf); // this is how it was stored
824824

825825
if (slice && slice->m_enable) {
826826
int offset, n;
@@ -1429,7 +1429,7 @@ LogAccess::marshal_plugin_identity_tag(char *buf)
14291429
if (!tag) {
14301430
tag = "*";
14311431
} else {
1432-
len = LogAccess::strlen(tag);
1432+
len = LogAccess::padded_strlen(tag);
14331433
}
14341434

14351435
if (buf) {
@@ -1463,7 +1463,7 @@ LogAccess::marshal_cache_lookup_url_canon(char *buf)
14631463
// If the lookup URL isn't populated, we'll fall back to the request URL.
14641464
len = marshal_client_req_url_canon(buf);
14651465
} else {
1466-
len = round_strlen(m_cache_lookup_url_canon_len + 1); // +1 for eos
1466+
len = padded_length(m_cache_lookup_url_canon_len + 1); // +1 for eos
14671467
if (buf) {
14681468
marshal_mem(buf, m_cache_lookup_url_canon_str, m_cache_lookup_url_canon_len, len);
14691469
}
@@ -1497,7 +1497,7 @@ LogAccess::marshal_client_sni_server_name(char *buf)
14971497
}
14981498
}
14991499
}
1500-
int len = round_strlen(server_name.length() + 1);
1500+
int len = padded_length(server_name.length() + 1);
15011501
if (buf) {
15021502
marshal_str(buf, server_name.data(), len);
15031503
}
@@ -1549,7 +1549,7 @@ int
15491549
LogAccess::marshal_version_build_number(char *buf)
15501550
{
15511551
auto &version = AppVersionInfo::get_version();
1552-
int len = LogAccess::strlen(version.build_number());
1552+
int len = LogAccess::padded_strlen(version.build_number());
15531553
if (buf) {
15541554
marshal_str(buf, version.build_number(), len);
15551555
}
@@ -1563,7 +1563,7 @@ int
15631563
LogAccess::marshal_version_string(char *buf)
15641564
{
15651565
auto &version = AppVersionInfo::get_version();
1566-
int len = LogAccess::strlen(version.version());
1566+
int len = LogAccess::padded_strlen(version.version());
15671567
if (buf) {
15681568
marshal_str(buf, version.version(), len);
15691569
}
@@ -1593,7 +1593,7 @@ LogAccess::marshal_proxy_protocol_version(char *buf)
15931593
version_str = "-";
15941594
break;
15951595
}
1596-
len = LogAccess::strlen(version_str);
1596+
len = LogAccess::padded_strlen(version_str);
15971597
}
15981598

15991599
if (buf) {
@@ -1815,7 +1815,7 @@ LogAccess::marshal_client_req_http_method(char *buf)
18151815
// buffer if str is nil, and we need room for this.
18161816
//
18171817
if (!str.empty()) {
1818-
plen = round_strlen(static_cast<int>(str.length()) + 1); // +1 for trailing 0
1818+
plen = padded_length(static_cast<int>(str.length()) + 1); // +1 for trailing 0
18191819
}
18201820
}
18211821

@@ -1831,7 +1831,7 @@ LogAccess::marshal_client_req_http_method(char *buf)
18311831
int
18321832
LogAccess::marshal_client_req_url(char *buf)
18331833
{
1834-
int len = round_strlen(m_client_req_url_len + 1); // +1 for trailing 0
1834+
int len = padded_length(m_client_req_url_len + 1); // +1 for trailing 0
18351835

18361836
if (buf) {
18371837
marshal_mem(buf, m_client_req_url_str, m_client_req_url_len, len);
@@ -1845,7 +1845,7 @@ LogAccess::marshal_client_req_url(char *buf)
18451845
int
18461846
LogAccess::marshal_client_req_url_canon(char *buf)
18471847
{
1848-
int len = round_strlen(m_client_req_url_canon_len + 1);
1848+
int len = padded_length(m_client_req_url_canon_len + 1);
18491849

18501850
if (buf) {
18511851
marshal_mem(buf, m_client_req_url_canon_str, m_client_req_url_canon_len, len);
@@ -1868,7 +1868,7 @@ LogAccess::marshal_client_req_unmapped_url_canon(char *buf)
18681868
// log the requests, even when there is no remap rule for it.
18691869
len = marshal_client_req_url_canon(buf);
18701870
} else {
1871-
len = round_strlen(m_client_req_unmapped_url_canon_len + 1); // +1 for eos
1871+
len = padded_length(m_client_req_unmapped_url_canon_len + 1); // +1 for eos
18721872
if (buf) {
18731873
marshal_mem(buf, m_client_req_unmapped_url_canon_str, m_client_req_unmapped_url_canon_len, len);
18741874
}
@@ -1891,7 +1891,7 @@ LogAccess::marshal_client_req_unmapped_url_path(char *buf)
18911891
if (m_client_req_unmapped_url_path_str == INVALID_STR) {
18921892
len = marshal_client_req_url_path(buf);
18931893
} else {
1894-
len = round_strlen(m_client_req_unmapped_url_path_len + 1); // +1 for eos
1894+
len = padded_length(m_client_req_unmapped_url_path_len + 1); // +1 for eos
18951895
if (buf) {
18961896
marshal_mem(buf, m_client_req_unmapped_url_path_str, m_client_req_unmapped_url_path_len, len);
18971897
}
@@ -1908,7 +1908,7 @@ LogAccess::marshal_client_req_unmapped_url_host(char *buf)
19081908
validate_unmapped_url();
19091909
validate_unmapped_url_path();
19101910

1911-
int len = round_strlen(m_client_req_unmapped_url_host_len + 1); // +1 for eos
1911+
int len = padded_length(m_client_req_unmapped_url_host_len + 1); // +1 for eos
19121912
if (buf) {
19131913
marshal_mem(buf, m_client_req_unmapped_url_host_str, m_client_req_unmapped_url_host_len, len);
19141914
}
@@ -1919,7 +1919,7 @@ LogAccess::marshal_client_req_unmapped_url_host(char *buf)
19191919
int
19201920
LogAccess::marshal_client_req_url_path(char *buf)
19211921
{
1922-
int len = round_strlen(m_client_req_url_path_len + 1);
1922+
int len = padded_length(m_client_req_url_path_len + 1);
19231923
if (buf) {
19241924
marshal_mem(buf, m_client_req_url_path_str, m_client_req_url_path_len, len);
19251925
}
@@ -1940,17 +1940,9 @@ LogAccess::marshal_client_req_url_scheme(char *buf)
19401940
alen = hdrtoken_index_to_length(scheme);
19411941
} else {
19421942
str = "UNKNOWN";
1943-
alen = strlen(str);
1944-
}
1945-
1946-
// calculate the padded length only if the actual length
1947-
// is not zero. We don't want the padded length to be zero
1948-
// because marshal_mem should write the DEFAULT_STR to the
1949-
// buffer if str is nil, and we need room for this.
1950-
//
1951-
if (alen) {
1952-
plen = round_strlen(alen + 1); // +1 for trailing 0
1943+
alen = ::strlen(str);
19531944
}
1945+
plen = padded_length(alen + 1); // +1 for trailing 0
19541946

19551947
if (buf) {
19561948
marshal_mem(buf, str, alen, plen);
@@ -1987,7 +1979,7 @@ int
19871979
LogAccess::marshal_client_req_protocol_version(char *buf)
19881980
{
19891981
const char *protocol_str = m_http_sm->get_user_agent().get_client_protocol();
1990-
int len = LogAccess::strlen(protocol_str);
1982+
int len = LogAccess::padded_strlen(protocol_str);
19911983

19921984
// Set major & minor versions when protocol_str is not "http/2".
19931985
if (::strlen(protocol_str) == 4 && strncmp("http", protocol_str, 4) == 0) {
@@ -2002,7 +1994,7 @@ LogAccess::marshal_client_req_protocol_version(char *buf)
20021994
protocol_str = "*";
20031995
}
20041996

2005-
len = LogAccess::strlen(protocol_str);
1997+
len = LogAccess::padded_strlen(protocol_str);
20061998
}
20071999

20082000
if (buf) {
@@ -2019,7 +2011,7 @@ int
20192011
LogAccess::marshal_server_req_protocol_version(char *buf)
20202012
{
20212013
const char *protocol_str = m_http_sm->server_protocol;
2022-
int len = LogAccess::strlen(protocol_str);
2014+
int len = LogAccess::padded_strlen(protocol_str);
20232015

20242016
// Set major & minor versions when protocol_str is not "http/2".
20252017
if (::strlen(protocol_str) == 4 && strncmp("http", protocol_str, 4) == 0) {
@@ -2034,7 +2026,7 @@ LogAccess::marshal_server_req_protocol_version(char *buf)
20342026
protocol_str = "*";
20352027
}
20362028

2037-
len = LogAccess::strlen(protocol_str);
2029+
len = LogAccess::padded_strlen(protocol_str);
20382030
}
20392031

20402032
if (buf) {
@@ -2189,7 +2181,7 @@ LogAccess::marshal_client_req_uuid(char *buf)
21892181
int len = snprintf(str, sizeof(str), "%s-%" PRId64 "", uuid, m_http_sm->sm_id);
21902182

21912183
ink_assert(len <= TS_CRUUID_STRING_LEN);
2192-
len = round_strlen(len + 1);
2184+
len = padded_length(len + 1);
21932185

21942186
if (buf) {
21952187
marshal_str(buf, str, len); // This will pad the remaining bytes properly ...
@@ -2209,7 +2201,7 @@ LogAccess::marshal_client_rx_error_code(char *buf)
22092201
{
22102202
char error_code[MAX_PROXY_ERROR_CODE_SIZE] = {0};
22112203
m_http_sm->t_state.client_info.rx_error_code.str(error_code, sizeof(error_code));
2212-
int round_len = LogAccess::strlen(error_code);
2204+
int round_len = LogAccess::padded_strlen(error_code);
22132205

22142206
if (buf) {
22152207
marshal_str(buf, error_code, round_len);
@@ -2223,7 +2215,7 @@ LogAccess::marshal_client_tx_error_code(char *buf)
22232215
{
22242216
char error_code[MAX_PROXY_ERROR_CODE_SIZE] = {0};
22252217
m_http_sm->t_state.client_info.tx_error_code.str(error_code, sizeof(error_code));
2226-
int round_len = LogAccess::strlen(error_code);
2218+
int round_len = LogAccess::padded_strlen(error_code);
22272219

22282220
if (buf) {
22292221
marshal_str(buf, error_code, round_len);
@@ -2238,7 +2230,7 @@ int
22382230
LogAccess::marshal_client_security_protocol(char *buf)
22392231
{
22402232
const char *proto = m_http_sm->get_user_agent().get_client_sec_protocol();
2241-
int round_len = LogAccess::strlen(proto);
2233+
int round_len = LogAccess::padded_strlen(proto);
22422234

22432235
if (buf) {
22442236
marshal_str(buf, proto, round_len);
@@ -2251,7 +2243,7 @@ int
22512243
LogAccess::marshal_client_security_cipher_suite(char *buf)
22522244
{
22532245
const char *cipher = m_http_sm->get_user_agent().get_client_cipher_suite();
2254-
int round_len = LogAccess::strlen(cipher);
2246+
int round_len = LogAccess::padded_strlen(cipher);
22552247

22562248
if (buf) {
22572249
marshal_str(buf, cipher, round_len);
@@ -2264,7 +2256,7 @@ int
22642256
LogAccess::marshal_client_security_curve(char *buf)
22652257
{
22662258
const char *curve = m_http_sm->get_user_agent().get_client_curve();
2267-
int round_len = LogAccess::strlen(curve);
2259+
int round_len = LogAccess::padded_strlen(curve);
22682260

22692261
if (buf) {
22702262
marshal_str(buf, curve, round_len);
@@ -2277,7 +2269,7 @@ int
22772269
LogAccess::marshal_client_security_group(char *buf)
22782270
{
22792271
const char *group = m_http_sm->get_user_agent().get_client_security_group();
2280-
int round_len = LogAccess::strlen(group);
2272+
int round_len = LogAccess::padded_strlen(group);
22812273

22822274
if (buf) {
22832275
marshal_str(buf, group, round_len);
@@ -2295,7 +2287,7 @@ LogAccess::marshal_client_security_alpn(char *buf)
22952287
alpn = client_sec_alpn.data();
22962288
}
22972289

2298-
int round_len = LogAccess::strlen(alpn);
2290+
int round_len = LogAccess::padded_strlen(alpn);
22992291

23002292
if (buf) {
23012293
marshal_str(buf, alpn, round_len);
@@ -2310,7 +2302,7 @@ LogAccess::marshal_client_security_alpn(char *buf)
23102302
int
23112303
LogAccess::marshal_proxy_resp_content_type(char *buf)
23122304
{
2313-
int len = round_strlen(m_proxy_resp_content_type_len + 1);
2305+
int len = padded_length(m_proxy_resp_content_type_len + 1);
23142306
if (buf) {
23152307
marshal_mem(buf, m_proxy_resp_content_type_str, m_proxy_resp_content_type_len, len);
23162308
}
@@ -2323,7 +2315,7 @@ LogAccess::marshal_proxy_resp_content_type(char *buf)
23232315
int
23242316
LogAccess::marshal_proxy_resp_reason_phrase(char *buf)
23252317
{
2326-
int len = round_strlen(m_proxy_resp_reason_phrase_len + 1);
2318+
int len = padded_length(m_proxy_resp_reason_phrase_len + 1);
23272319
if (buf) {
23282320
marshal_mem(buf, m_proxy_resp_reason_phrase_str, m_proxy_resp_reason_phrase_len, len);
23292321
}
@@ -2629,7 +2621,7 @@ LogAccess::marshal_server_host_name(char *buf)
26292621

26302622
if (m_http_sm->t_state.current.server) {
26312623
str = m_http_sm->t_state.current.server->name;
2632-
len = LogAccess::strlen(str);
2624+
len = LogAccess::padded_strlen(str);
26332625
}
26342626

26352627
if (buf) {
@@ -3189,7 +3181,7 @@ LogAccess::marshal_http_header_field(LogField::Container container, char *field,
31893181
buf++;
31903182
}
31913183
running_len += 1;
3192-
padded_len = round_strlen(running_len);
3184+
padded_len = padded_length(running_len);
31933185

31943186
// Note: marshal_string fills the padding to
31953187
// prevent purify UMRs so we do it here too
@@ -3294,7 +3286,7 @@ LogAccess::marshal_http_header_field_escapify(LogField::Container container, cha
32943286
buf++;
32953287
}
32963288
running_len += 1;
3297-
padded_len = round_strlen(running_len);
3289+
padded_len = padded_length(running_len);
32983290

32993291
// Note: marshal_string fills the padding to
33003292
// prevent purify UMRs so we do it here too

0 commit comments

Comments
 (0)