fix printing of long hex values
authorAlan T. DeKok <aland@freeradius.org>
Mon, 5 Jun 2017 14:47:29 +0000 (10:47 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 5 Jun 2017 14:47:29 +0000 (10:47 -0400)
src/lib/value.c

index 888ca8a..ca18327 100644 (file)
@@ -1738,34 +1738,67 @@ print_int:
        case PW_TYPE_OCTETS:
        case PW_TYPE_TLV:
        {
-               size_t max;
+               size_t binlen;
+               size_t hexlen;
 
-               /* Return the number of bytes we would have written */
-               len = (inlen * 2) + 2;
-               if (freespace <= 1) {
-                       return len;
-               }
+               binlen = inlen;
+               hexlen = (binlen * 2) + 2; /* NOT accounting for trailing NUL */
 
-               *out++ = '0';
-               freespace--;
+               /*
+                *      If the buffer is too small, put something into
+                *      it, and return how much we should have written
+                *
+                *      0 + x + H + H + NUL = 5
+                */
+               if (freespace < 5) {
+                       switch (freespace) {
+                       case '4':
+                       case '3':
+                               out[0] = '0';
+                               out[1] = 'x';
+                               out[2] = '\0';
+                               return hexlen;
+
+                       case 2:
+                               *out = '0';
+                               out++;
+                               /* FALL-THROUGH */
+
+                       case 1:
+                               *out = '\0';
+                               break;
+
+                       case 0:
+                               break;
+                       }
 
-               if (freespace <= 1) {
-                       *out = '\0';
-                       return len;
+                       return hexlen;
                }
-               *out++ = 'x';
-               freespace--;
 
-               if (freespace <= 2) {
-                       *out = '\0';
-                       return len;
+               /*
+                *      The output buffer is at least 5 bytes, we haev
+                *      room for '0xHH' plus a trailing NUL byte.
+                */
+               out[0] = '0';
+               out[1] = 'x';
+
+               /*
+                *      Get maximum number of bytes we can encode
+                *      given freespace, ensuring we account for '0',
+                *      'x', and the trailing NUL in the buffer.
+                *
+                *      Note that we can't have "freespace = 0" after
+                *      this, as 'freespace' has to be at least 5.
+                */
+               freespace -= 3;
+               freespace /= 2;
+               if (binlen > freespace) {
+                       binlen = freespace;
                }
 
-               /* Get maximum number of bytes we can encode given freespace */
-               max = ((freespace % 2) ? freespace - 1 : freespace - 2) / 2;
-               fr_bin2hex(out, data->octets, ((size_t)inlen > max) ? max : (size_t)inlen);
+               fr_bin2hex(out + 2, data->octets, binlen);
+               return hexlen;
        }
-               return len;
 
        case PW_TYPE_IFID:
                a = ifid_ntoa(buf, sizeof(buf), data->ifid);