Welcome to little lamb

Code » limb » commit a688eae

base_scan(): Add strict mode to require full padding..

author Olivier Brunel
2023-04-22 13:29:07 UTC
committer Olivier Brunel
2023-05-20 18:06:37 UTC
parent ca4f5389d2b6227ef4cb7a9acc1e0fdb1ef8a18f

base_scan(): Add strict mode to require full padding..

..and also check that none of the unused bits were set.

src/doc/base.h/base_fmt.3.md +9 -4
src/doc/base32.h/base32_fmt.3.md +3 -2
src/doc/base64.h/base64_fmt.3.md +3 -2
src/liblimb/base.h/base_scan.c +12 -3
src/liblimb/base32.h/base32_scan.c +2 -2
src/liblimb/base64.h/base64_scan.c +2 -2
src/liblimb/include/limb/base.h +1 -1
src/liblimb/include/limb/base32.h +1 -1
src/liblimb/include/limb/base64.h +1 -1

diff --git a/src/doc/base.h/base_fmt.3.md b/src/doc/base.h/base_fmt.3.md
index ca3535d..ee5a2d5 100644
--- a/src/doc/base.h/base_fmt.3.md
+++ b/src/doc/base.h/base_fmt.3.md
@@ -11,7 +11,7 @@ base\_fmt - base-16/32/64/128 encode/decode a byte array
 
 ```pre hl
 ssize_t base_fmt(char *<em>dst</em>, int <em>base</em>, const char *<em>data</em>, size_t <em>dlen</em>, const char *<em>alpha</em>, int <em>strict</em>)
-ssize_t base_scan(char *<em>dst</em>, int <em>base</em>, const char *<em>data</em>, size_t <em>dlen</em>, const char *<em>alpha</em>)
+ssize_t base_scan(char *<em>dst</em>, int <em>base</em>, const char *<em>data</em>, size_t <em>dlen</em>, const char *<em>alpha</em>, int <em>strict</em>)
 ```
 
 # DESCRIPTION
@@ -35,7 +35,12 @@ length `dlen` into the byte array pointed to be `dst` using the base algorithm
 specified with `base` and the alphabet pointed to by `alpha`.
 
 Both arguments `base` and `alpha` are similar than their counterparts for
-`base_fmt`().
+`base_fmt`(). Argument `strict` is similar as well, in that if non-zero it will
+require all necessary padding, but with zero it will accept a single padding
+character indicating padding.
+
+Additionally, when `strict` is non-zero any base-encoded data were at least one
+unused bit was set will result in an error.
 
 The encoded `data` doesn't have to end with proper padding, that is a single
 padding character marking the end of data is enough (as done with `base_fmt`()
@@ -46,7 +51,7 @@ only data validation is performed and the length required in `dst` is returned.
 ! INFO:
 ! Both functions implement algorithms that can be used to perform encoding
 ! and decoding as described in [RFC 4648][rfc4648], assuming corresponding
-! alphabet is used.
+! alphabet is used (and `strict` is non-zero).
 
 [rfc4648] (https://datatracker.ietf.org/doc/html/rfc4648)
 
@@ -66,7 +71,7 @@ The `base_fmt`() and `base_scan`() functions may fail if :
 The `base_scan`() function may also fail if :
 
 : *EINVAL*
-:: The input `data` is invalid, i.e. contains a character not from `alpha`.
+:: The input `data` is invalid, e.g. contains a character not from `alpha`.
 
 # SEE ALSO
 
diff --git a/src/doc/base32.h/base32_fmt.3.md b/src/doc/base32.h/base32_fmt.3.md
index 4a42e53..b3fed8d 100644
--- a/src/doc/base32.h/base32_fmt.3.md
+++ b/src/doc/base32.h/base32_fmt.3.md
@@ -11,7 +11,7 @@ base32\_fmt, base32\_scan - base32 encode/decode a byte array
 
 ```pre hl
 size_t base32_fmt(char *<em>dst</em>, const void *<em>data</em>, size_t <em>dlen</em>, int <em>strict</em>)
-ssize_t base32_scan(char *<em>dst</em>, const char *<em>data</em>, size_t <em>dlen</em>)
+ssize_t base32_scan(char *<em>dst</em>, const char *<em>data</em>, size_t <em>dlen</em>, int <em>strict</em>)
 ```
 
 # DESCRIPTION
@@ -25,7 +25,8 @@ Refer to [base_fmt](3) for more details.
 
 The `base32_scan`() function will decode the byte array pointed to by `data` of
 length `dlen` into the byte array pointed to be `dst` using the base32 algorithm
-as described in [RFC 4648][rfc4648].
+as described in [RFC 4648][rfc4648], unless `strict` is zero if which case it
+accepts a single padding character to indicate padding.
 
 Refer to [base_scan](3) for more details.
 
diff --git a/src/doc/base64.h/base64_fmt.3.md b/src/doc/base64.h/base64_fmt.3.md
index eabce51..3ee1a3b 100644
--- a/src/doc/base64.h/base64_fmt.3.md
+++ b/src/doc/base64.h/base64_fmt.3.md
@@ -11,7 +11,7 @@ base64\_fmt, base64\_scan - base64 encode/decode a byte array
 
 ```pre hl
 size_t base64_fmt(char *<em>dst</em>, const void *<em>data</em>, size_t <em>dlen</em>, int <em>strict</em>)
-ssize_t base64_scan(char *<em>dst</em>, const char *<em>data</em>, size_t <em>dlen</em>)
+ssize_t base64_scan(char *<em>dst</em>, const char *<em>data</em>, size_t <em>dlen</em>, int <em>strict</em>)
 ```
 
 # DESCRIPTION
@@ -25,7 +25,8 @@ Refer to [base_fmt](3) for more details.
 
 The `base64_scan`() function will decode the byte array pointed to by `data` of
 length `dlen` into the byte array pointed to be `dst` using the base64 algorithm
-as described in [RFC 4648][rfc4648].
+as described in [RFC 4648][rfc4648], unless `strict` is zero if which case it
+accepts a single padding character to indicate padding.
 
 Refer to [base_scan](3) for more details.
 
diff --git a/src/liblimb/base.h/base_scan.c b/src/liblimb/base.h/base_scan.c
index 130ed02..3462ba6 100644
--- a/src/liblimb/base.h/base_scan.c
+++ b/src/liblimb/base.h/base_scan.c
@@ -7,7 +7,7 @@
 #include <limb/u64.h>
 
 ssize_t
-base_scan(char *dst, int base, const char *data, size_t dlen, const char *alpha)
+base_scan(char *dst, int base, const char *data, size_t dlen, const char *alpha, int strict)
 {
     size_t bits, bin, bout;
     ssize_t w = 0;
@@ -23,6 +23,9 @@ base_scan(char *dst, int base, const char *data, size_t dlen, const char *alpha)
         default: return (errno = ERANGE, -1);
     }
 
+    if (strict && dlen % bin)
+        return (errno = EINVAL, -1);
+
     while (dlen) {
         size_t l = (dlen > bin) ? bin : dlen;
         size_t e = (size_t) -1;
@@ -45,9 +48,15 @@ base_scan(char *dst, int base, const char *data, size_t dlen, const char *alpha)
         u64p_be(&u);
 
         size_t n = bout;
-        /* padding means writing less than bout bytes */
-        if (e != (size_t) -1)
+        /* was there padding? */
+        if (e != (size_t) -1) {
+            /* if strict, check none of the unused bits were set */
+            if (strict && (byte_chr(alpha, base + 1, data[e - 1])
+                        & ((1 << ((bits * e) % 8)) - 1)))
+                return (errno = EINVAL, -1);
+            /* padding means writing less than bout bytes */
             n = bout * e / bin;
+        }
         /* less than bin bytes in /requires/ padding */
         if (l < bin && e == (size_t) -1)
             return (errno = EINVAL, -1);
diff --git a/src/liblimb/base32.h/base32_scan.c b/src/liblimb/base32.h/base32_scan.c
index 92f7f18..9f12f47 100644
--- a/src/liblimb/base32.h/base32_scan.c
+++ b/src/liblimb/base32.h/base32_scan.c
@@ -7,7 +7,7 @@
 const char base32[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=";
 
 ssize_t
-base32_scan(char *dst, const char *data, size_t dlen)
+base32_scan(char *dst, const char *data, size_t dlen, int strict)
 {
-    return base_scan(dst, 32, data, dlen, base32);
+    return base_scan(dst, 32, data, dlen, base32, strict);
 }
diff --git a/src/liblimb/base64.h/base64_scan.c b/src/liblimb/base64.h/base64_scan.c
index 969d368..8b7989d 100644
--- a/src/liblimb/base64.h/base64_scan.c
+++ b/src/liblimb/base64.h/base64_scan.c
@@ -7,7 +7,7 @@
 const char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 
 ssize_t
-base64_scan(char *dst, const char *data, size_t dlen)
+base64_scan(char *dst, const char *data, size_t dlen, int strict)
 {
-    return base_scan(dst, 64, data, dlen, base64);
+    return base_scan(dst, 64, data, dlen, base64, strict);
 }
diff --git a/src/liblimb/include/limb/base.h b/src/liblimb/include/limb/base.h
index c5e0cea..d1af909 100644
--- a/src/liblimb/include/limb/base.h
+++ b/src/liblimb/include/limb/base.h
@@ -7,6 +7,6 @@
 #include <sys/types.h> /* ssize_t */
 
 extern ssize_t base_fmt(char *dst, int base, const char *data, size_t dlen, const char *alpha, int strict);
-extern ssize_t base_scan(char *dst, int base, const char *data, size_t dlen, const char *alpha);
+extern ssize_t base_scan(char *dst, int base, const char *data, size_t dlen, const char *alpha, int strict);
 
 # endif /* LIMB_BASE_H */
diff --git a/src/liblimb/include/limb/base32.h b/src/liblimb/include/limb/base32.h
index cdaa70c..b3c6b82 100644
--- a/src/liblimb/include/limb/base32.h
+++ b/src/liblimb/include/limb/base32.h
@@ -7,6 +7,6 @@
 #include <sys/types.h> /* ssize_t */
 
 extern size_t base32_fmt(char *dst, const void *data, size_t dlen, int strict);
-extern ssize_t base32_scan(char *dst, const char *data, size_t dlen);
+extern ssize_t base32_scan(char *dst, const char *data, size_t dlen, int strict);
 
 # endif /* LIMB_BASE32_H */
diff --git a/src/liblimb/include/limb/base64.h b/src/liblimb/include/limb/base64.h
index a617121..8162cbc 100644
--- a/src/liblimb/include/limb/base64.h
+++ b/src/liblimb/include/limb/base64.h
@@ -7,6 +7,6 @@
 #include <sys/types.h> /* ssize_t */
 
 extern size_t base64_fmt(char *dst, const void *data, size_t dlen, int strict);
-extern ssize_t base64_scan(char *dst, const char *data, size_t dlen);
+extern ssize_t base64_scan(char *dst, const char *data, size_t dlen, int strict);
 
 # endif /* LIMB_BASE64_H */