The unpac monorepo manager self-hosting as a monorepo using unpac

Merge pull request #43 from mirage/fix-base64

Be more strict about padding

authored by dinosaure.tngl.sh and committed by

GitHub 6227924a ca1db401

+48 -7
+17 -5
src/base64.ml
··· 65 65 can raise and avoid appearance of unknown exceptions like an ex-nihilo 66 66 magic rabbit (or magic money?). *) 67 67 exception Out_of_bounds 68 + exception Too_much_input 68 69 69 70 let get_uint8 t off = 70 71 if off < 0 || off >= String.length t then raise Out_of_bounds ; ··· 153 154 let n = (len // 4) * 4 in 154 155 let n' = (n // 4) * 3 in 155 156 let res = Bytes.create n' in 157 + let invalid_pad_overflow = pad in 156 158 157 159 let get_uint8_or_padding = 158 160 if pad then (fun t i -> if i >= len then raise Out_of_bounds ; get_uint8 t (off + i) ) ··· 233 235 if i + 4 = n 234 236 (* end of input in anyway *) 235 237 then match pad with 236 - | 0 -> 0 237 - | 4 -> 3 238 + | 0 -> 239 + 0 240 + | 4 -> 241 + (* assert (invalid_pad_overflow = false) ; *) 242 + 3 238 243 (* [get_uint8] lies and if we get [4], that mean we got one or more (at 239 244 most 4) padding character. In this situation, because we round length 240 245 of [res] (see [n // 4]), we need to delete 3 bytes. *) 241 - | pad -> pad 246 + | pad -> 247 + pad 242 248 else match pad with 243 249 | 0 -> dec (j + 3) (i + 4) 244 - | 4 -> only_padding 3 (i + 4) 250 + | 4 -> 251 + (* assert (invalid_pad_overflow = false) ; *) 252 + only_padding 3 (i + 4) 245 253 (* Same situation than above but we should get only more padding 246 254 characters then. *) 247 - | pad -> only_padding pad (i + 4) end in 255 + | pad -> 256 + if invalid_pad_overflow = true then raise Too_much_input ; 257 + only_padding pad (i + 4) end in 248 258 249 259 match dec 0 0 with 250 260 | 0 -> Ok (Bytes.unsafe_to_string res, 0, n') ··· 254 264 | exception Not_found -> 255 265 (* appear when one character of [input] ∉ [alphabet] and this character <> '=' *) 256 266 error_msgf "Malformed input" 267 + | exception Too_much_input -> 268 + error_msgf "Too much input" 257 269 258 270 let decode ?pad ?(alphabet = default_alphabet) ?off ?len input = 259 271 match decode_sub ?pad alphabet ?off ?len input with
+31 -2
test/test.ml
··· 69 69 2, 0, "", "BB"; 70 70 ] 71 71 72 + let nocrypto_tests = 73 + [ "\x00\x5a\x6d\x39\x76", None 74 + ; "\x5a\x6d\x39\x76", Some "\x66\x6f\x6f" 75 + ; "\x5a\x6d\x39\x76\x76", None 76 + ; "\x5a\x6d\x39\x76\x76\x76", None 77 + ; "\x5a\x6d\x39\x76\x76\x76\x76", None 78 + ; "\x5a\x6d\x39\x76\x00", None 79 + ; "\x5a\x6d\x39\x76\x62\x77\x3d\x3d", Some "\x66\x6f\x6f\x6f" 80 + ; "\x5a\x6d\x39\x76\x62\x77\x3d\x3d\x00", None 81 + ; "\x5a\x6d\x39\x76\x62\x77\x3d\x3d\x00\x01", None 82 + ; "\x5a\x6d\x39\x76\x62\x77\x3d\x3d\x00\x01\x02", None 83 + ; "\x5a\x6d\x39\x76\x62\x77\x3d\x3d\x00\x01\x02\x03", None 84 + ; "\x5a\x6d\x39\x76\x62\x32\x38\x3d", Some "\x66\x6f\x6f\x6f\x6f" 85 + ; "\x5a\x6d\x39\x76\x62\x32\x39\x76", Some "\x66\x6f\x6f\x6f\x6f\x6f" 86 + ; "YWE=", Some "aa" 87 + ; "YWE==", None 88 + ; "YWE===", None 89 + ; "YWE=====", None 90 + ; "YWE======", None ] 91 + 72 92 let alphabet_size () = 73 93 List.iter (fun (name,alphabet) -> 74 94 Alcotest.(check int) (sprintf "Alphabet size %s = 64" name) ··· 118 138 let test_cfcs () = 119 139 List.iter (fun (off, len, c,r) -> 120 140 Alcotest.(check string) (sprintf "decode %s" r) c (Base64.decode_exn ~pad:false ~off ~len r); 121 - ) cfcs_tests 141 + ) cfcs_tests 142 + 143 + let test_nocrypto () = 144 + List.iter (fun (input, res) -> 145 + let res' = match Base64.decode ~pad:true input with 146 + | Ok v -> Some v 147 + | Error _ -> None in 148 + Alcotest.(check (option string)) (sprintf "decode %S" input) res' res ; 149 + ) nocrypto_tests 122 150 123 151 exception Malformed 124 152 exception Wrong_padding ··· 217 245 ; "RFC3548 test vectors", `Quick, test_rfc3548 218 246 ; "Hannes test vectors", `Quick, test_hannes 219 247 ; "Cfcs test vectors", `Quick, test_cfcs 220 - ; "PHP test vectors", `Quick, test_php ] 248 + ; "PHP test vectors", `Quick, test_php 249 + ; "Nocrypto test vectors", `Quick, test_nocrypto ] 221 250 222 251 let () = 223 252 Alcotest.run "Base64" [