From: Alan T. DeKok Date: Tue, 2 Dec 2025 17:35:30 +0000 (-0500) Subject: add and use FR_DBUFF_ERROR_OFFSET X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7f113f81ba7777f6bb109d092204afa0fca1dda8;p=thirdparty%2Ffreeradius-server.git add and use FR_DBUFF_ERROR_OFFSET so that we don't have int64 underflow when subtracting offsets from error slen arguably we should instead have an error pointer like is done in the sbuffs, and with fr_sbuff_error() --- diff --git a/src/lib/util/dbuff.h b/src/lib/util/dbuff.h index f613c11bd1c..32e64f2ff1b 100644 --- a/src/lib/util/dbuff.h +++ b/src/lib/util/dbuff.h @@ -189,6 +189,14 @@ do { \ if (_slen < 0) return _slen; \ } while (0) +/** Generic wrapper to return an error and an offset from encoding. + * + * Some encoders return PAIR_ENCODE_FATAL_ERROR. Substracting an + * offset from that values means it wraps be be a positive number + * near INT64_MAX. This macro ensures that doesn't happen. + */ +#define FR_DBUFF_ERROR_OFFSET(_slen, _offset) ((_slen < INT32_MAX) ? _slen : _slen - (ssize_t) _offset) + /** @name Initialisers * @{ */ diff --git a/src/protocols/cbor/base.c b/src/protocols/cbor/base.c index 77c31d3de56..fd6f2f970cb 100644 --- a/src/protocols/cbor/base.c +++ b/src/protocols/cbor/base.c @@ -30,7 +30,7 @@ static ssize_t decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t } slen = fr_cbor_decode_pair(ctx, out, &dbuff, parent, false); - if (slen <= 0) return slen - fr_dbuff_used(&dbuff); + if (slen <= 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&dbuff)); } while (true); return fr_dbuff_used(&dbuff); @@ -49,7 +49,7 @@ static ssize_t encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED void ssize_t slen; slen = fr_cbor_encode_pair(&work_dbuff, vp); - if (slen <= 0) return slen - fr_dbuff_used(&work_dbuff); + if (slen <= 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&work_dbuff)); } FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) 0xff); /* end of indefinite array */ diff --git a/src/protocols/dhcpv6/base.c b/src/protocols/dhcpv6/base.c index 9c147b0c8d0..6b104bedba0 100644 --- a/src/protocols/dhcpv6/base.c +++ b/src/protocols/dhcpv6/base.c @@ -791,7 +791,7 @@ ssize_t fr_dhcpv6_encode(fr_dbuff_t *dbuff, uint8_t const *original, size_t leng fr_pair_dcursor_iter_init(&cursor, vps, fr_dhcpv6_next_encodable, dict_dhcpv6); while ((fr_dbuff_extend(&frame_dbuff) > 0) && (fr_dcursor_current(&cursor) != NULL)) { slen = fr_dhcpv6_encode_option(&frame_dbuff, &cursor, &packet_ctx); - if (slen < 0) return slen - fr_dbuff_used(&frame_dbuff); + if (slen < 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&frame_dbuff)); } return fr_dbuff_set(dbuff, &frame_dbuff); diff --git a/src/protocols/dns/encode.c b/src/protocols/dns/encode.c index fe43f3bec65..f0b6be20bef 100644 --- a/src/protocols/dns/encode.c +++ b/src/protocols/dns/encode.c @@ -486,25 +486,25 @@ ssize_t fr_dns_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_dns_ctx_t *pack * Encode questions */ slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_question, packet_ctx, packet + 4); - if (slen < 0) return slen - fr_dbuff_used(&work_dbuff); + if (slen < 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&work_dbuff)); /* * Encode answers */ slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_rr, packet_ctx, packet + 6); - if (slen < 0) return slen - fr_dbuff_used(&work_dbuff); + if (slen < 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&work_dbuff)); /* * Encode NS records */ slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_ns, packet_ctx, packet + 8); - if (slen < 0) return slen - fr_dbuff_used(&work_dbuff); + if (slen < 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&work_dbuff)); /* * Encode additional records */ slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_ar, packet_ctx, packet + 10); - if (slen < 0) return slen - fr_dbuff_used(&work_dbuff); + if (slen < 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&work_dbuff)); return fr_dbuff_set(dbuff, &work_dbuff); } diff --git a/src/protocols/tacacs/encode.c b/src/protocols/tacacs/encode.c index fa4d3b194e2..a841fc2bf07 100644 --- a/src/protocols/tacacs/encode.c +++ b/src/protocols/tacacs/encode.c @@ -220,7 +220,7 @@ static ssize_t tacacs_encode_body_arg_n(fr_dbuff_t *dbuff, uint8_t arg_cnt, uint if (child_argc > (arg_cnt - i)) child_argc = arg_cnt = i; slen = tacacs_encode_body_arg_n(&work_dbuff, child_argc, &arg_len[i], &vp->vp_group, vp->da); - if (slen < 0) return slen - fr_dbuff_used(&work_dbuff); + if (slen < 0) return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&work_dbuff)); i += child_argc; continue;