-
Notifications
You must be signed in to change notification settings - Fork 657
[DISCUSS] Add a SBuf-based Base64 encoder/decoder #2452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
aaebdbd
89cb57e
61a4b13
22ac40d
dd9ee76
855f4ae
d9a6d20
c05f111
8b99377
19d81a9
1ccf9c2
6d2e4ce
b0ee46b
468c947
049689e
49a94cc
166a4eb
930402d
5d7993b
1c7a989
6c8d181
d4aebc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* | ||
| * Copyright (C) 1996-2026 The Squid Software Foundation and contributors | ||
| * | ||
| * Squid software is distributed under GPLv2+ license and includes | ||
| * contributions from numerous individuals and organizations. | ||
| * Please see the COPYING and CONTRIBUTORS files for details. | ||
| */ | ||
|
|
||
| #include "squid.h" | ||
| #include "anyp/Base64.h" | ||
| #include "base64.h" | ||
| #include "sbuf/SBuf.h" | ||
|
|
||
| SBuf Base64Encode(const char *input, size_t length) | ||
| { | ||
| SBuf result; | ||
| const auto encodedLength = BASE64_ENCODE_RAW_LENGTH(length); | ||
| char *buf = result.rawAppendStart(encodedLength); | ||
| base64_encode_raw(buf, length, reinterpret_cast<const uint8_t *>(input)); | ||
| result.rawAppendFinish(buf, encodedLength); | ||
| return result; | ||
| } | ||
|
|
||
| SBuf Base64Encode(const SBuf &input) | ||
| { | ||
| return Base64Encode(input.rawContent(), input.length()); | ||
| } | ||
|
|
||
| SBuf Base64Decode(const char *input, size_t length) | ||
| { | ||
| struct base64_decode_ctx ctx; | ||
| base64_decode_init(&ctx); | ||
|
|
||
| SBuf result; | ||
| const auto maxDecodedLength = BASE64_DECODE_LENGTH(length); | ||
| uint8_t *buf = reinterpret_cast<uint8_t *>(result.rawAppendStart(maxDecodedLength)); | ||
|
|
||
| size_t decodedLength = 0; | ||
| if (!base64_decode_update(&ctx, &decodedLength, buf, length, input)) | ||
| throw DecodeException("base64 decode error: invalid input", Here()); | ||
| if (!base64_decode_final(&ctx)) | ||
| throw DecodeException("base64 decode error: incomplete input", Here()); | ||
|
|
||
| result.rawAppendFinish(reinterpret_cast<char *>(buf), decodedLength); | ||
| return result; | ||
| } | ||
|
|
||
| SBuf Base64Decode(const SBuf &input) | ||
| { | ||
| return Base64Decode(input.rawContent(), input.length()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * Copyright (C) 1996-2026 The Squid Software Foundation and contributors | ||
| * | ||
| * Squid software is distributed under GPLv2+ license and includes | ||
| * contributions from numerous individuals and organizations. | ||
| * Please see the COPYING and CONTRIBUTORS files for details. | ||
| */ | ||
|
|
||
| #ifndef SQUID_SRC_ANYP_BASE64_H | ||
| #define SQUID_SRC_ANYP_BASE64_H | ||
|
|
||
| #include "base/TextException.h" | ||
| #include "sbuf/forward.h" | ||
|
|
||
| /// Thrown by Base64Decode() when the input is not valid base64. | ||
| class DecodeException : public TextException | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not introduce a custom exception type to report decoding errors, especially when that type is effectively unused outside of unit tests. Instead, return This is the second time we are discussing a recent attempt to throw from a decoding function. The first one resulted in a |
||
| { | ||
| public: | ||
| using TextException::TextException; | ||
| }; | ||
|
|
||
| SBuf Base64Encode(const char *input, size_t length); | ||
| SBuf Base64Encode(const SBuf &input); | ||
|
|
||
| /// Decodes a base64-encoded string. Throws DecodeException on invalid input. | ||
| SBuf Base64Decode(const char *input, size_t length); | ||
| SBuf Base64Decode(const SBuf &input); | ||
|
|
||
| #endif /* SQUID_SRC_ANYP_BASE64_H */ | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given how many cases were missed by recent commit 74b1276 and followup commit 19a590c, I think this PR should rename
base64_encode_update()declared below tobase64_encode_updateXXX(). We clearly cannot rely on PR authors finding remaining relevant cases; we need the compiler to flag them for us. Hopefully, after this PR, there will not be many such cases left.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. base64_encode_update() is part of the libnettle API, of which this file is an extract for systems that do not carry it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given how many cases were missed by recent commit 74b1276 and followup commit 19a590c, I think a better reaction would look more like this:
Sounds good, and I will also add a trivial wrapper with the same
base64_encode_updateXXX()name to keep libnettle-based builds happy.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, but I do not plan to add a trivial wrapper.
This PR is about implementing a new API, and doing MVP clients to ensure it works as intended, as per common practice. Once this effort completes, there should be very few mentions of
base64[^ ]*(case-sensitive) in the codebase.Main exceptions will be:
git grep base64will be good enough to identify all trouble spots; there is no added value from the proposed out-of-scope changeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That logic has failed us twice already. We could get lucky the third time, of course, but I recommend avoiding that risk instead.
IMO, there clearly is value in explicitly marking problematic APIs as such. And the proposed change can easily be viewed as in-scope -- it self-documents which API must be used in new code whenever feasible (to avoid the
XXX). If this PR claims that hiding the problematic API is out of scope, then please make sure this PR explicitly documents which of the two available APIs the folks should use whenever feasible.