]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add and use FR_DBUFF_ERROR_OFFSET
authorAlan T. DeKok <aland@freeradius.org>
Tue, 2 Dec 2025 17:35:30 +0000 (12:35 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 2 Dec 2025 18:50:26 +0000 (13:50 -0500)
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()

src/lib/util/dbuff.h
src/protocols/cbor/base.c
src/protocols/dhcpv6/base.c
src/protocols/dns/encode.c
src/protocols/tacacs/encode.c

index f613c11bd1cf7f12b7c883e81b37568639df5491..32e64f2ff1b14c14d9709f3018d6b56da922a5e6 100644 (file)
@@ -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
  * @{
  */
index 77c31d3de56e355ecc66b89d2fc04aa765939bd8..fd6f2f970cb1a73f05cadb6e9ef05c85d62eec36 100644 (file)
@@ -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 */
index 9c147b0c8d021a5955dcbd20804bdcf5b5153a7d..6b104bedba0e57849d9e5f3d32cc128d9e2ca3ad 100644 (file)
@@ -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);
index fe43f3bec65f031997d2b047be675da50d3183bd..f0b6be20befcf07aa597af99762161cd8b74e88a 100644 (file)
@@ -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);
 }
index fa4d3b194e246773a8e225a6afb35044ab213f20..a841fc2bf073383410283196eb719e9a217469a1 100644 (file)
@@ -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;