Skip to content
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

Fix UNSAFE_TODO for wallet #26253

Merged
merged 3 commits into from
Nov 6, 2024
Merged

Fix UNSAFE_TODO for wallet #26253

merged 3 commits into from
Nov 6, 2024

Conversation

supermassive
Copy link
Collaborator

@supermassive supermassive commented Oct 28, 2024

Resolves brave/brave-browser#41664

Fixing #pragma allow_unsafe_buffers and UNSAFE_TODO in wallet. Mostly this comes with using base::span (with compile-time size preferably) and adjusting dependent code.

Submitter Checklist:

  • I confirm that no security/privacy review is needed and no other type of reviews are needed, or that I have requested them
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally:
    • npm run test -- brave_browser_tests, npm run test -- brave_unit_tests wiki
    • npm run presubmit wiki, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

components/brave_wallet/browser/internal/hd_key.h Outdated Show resolved Hide resolved
if (byte <= 0xf) {
std::string one_char_byte;
base::AppendHexEncodedByte(byte, one_char_byte, false);
result += one_char_byte[1];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base::StrAppend?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just adds a single char, StrAppend is for appending many strings so doesn't fit here

components/brave_wallet/common/hex_utils.cc Outdated Show resolved Hide resolved
@supermassive supermassive marked this pull request as draft October 29, 2024 07:16
@supermassive supermassive force-pushed the fix_unsafe_todo branch 4 times, most recently from b2b95b6 to 4162d1e Compare November 1, 2024 06:14
@supermassive supermassive marked this pull request as ready for review November 1, 2024 11:24
Copy link
Member

@darkdh darkdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++ with few nits

return std::nullopt;
}

// Parse first hop address.
path.push_back("0x" + HexEncodeLower(data.data(), 20));
offset += 20;
path.push_back("0x" + HexEncodeLower(*reader.Read(20u)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base::StrCat?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@@ -51,30 +45,26 @@ TEST(PermissionUtilsUnitTest, GetConcatOriginFromWalletAddresses) {
}};

url::Origin origin = url::Origin::Create(GURL("https://test.com"));
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); ++i) {
for (auto& test_case : cases) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const auto&

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

kBraveWalletPageGeneratedSize)),
IDR_WALLET_PAGE_HTML);
webui::SetupWebUIDataSource(source,
base::make_span(kBraveWalletPageGenerated),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and all the other cases should be just base::span, and rely on CTAD. I say should because there could be a rare case where you still may need base::make_span until this CL lands through 132, but I think it would be good if we replaced base::make_span with base:span wherever it is possible to.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -71,7 +73,7 @@ class DiscoverAccountTaskBase {
uint32_t active_requests_ = 0;
// Indexed by 0 and 1 for receive and change addresses discovery states
// respectively.
State states_[2];
std::array<State, 2> states_;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but IMO it hides the original problem here: that we are using some arbitrary index to access two static states. I've went looking around and it seems the issue starts here:

struct BitcoinKeyId {
  uint32 change;
  uint32 index;
};

So we are storing this index as a number, when in fact there is only two options, namely, kBitcoinReceiveIndex and kBitcoinChangeIndex.

I think we should consider changing this into two fields, and actually turning BitcoinKeyId.index into BitcoinKeyId.type, the type being an enum. What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point and I believe there is a TODO somewhere to switch to enum or a bool there. But that would be too much for this PR.

@cdesouza-chromium
Copy link
Collaborator

Would it be possible to break apart this PR into smaller separate PRs that are more manageable to review? These are more than mechanical changes, and I feel we could be missing things due to the sheer size of it.

Copy link
Contributor

github-actions bot commented Nov 4, 2024

[puLL-Merge] - brave/brave-core@26253

Description

This PR makes significant changes to improve memory safety and modernize the codebase. It primarily replaces unsafe buffer handling with safer constructs, updates function signatures to use more appropriate types, and removes some compiler-specific workarounds.

Changes

Changes

  1. browser/ui/webui/brave_wallet/android/android_wallet_page_ui.cc:

    • Replaced UNSAFE_TODO(base::make_span()) with base::span().
  2. browser/ui/webui/brave_wallet/ledger/ledger_ui.cc:

    • Replaced UNSAFE_TODO(base::make_span()) with base::span().
  3. browser/ui/webui/brave_wallet/line_chart/line_chart_ui.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Replaced base::make_span() with base::span().
  4. browser/ui/webui/brave_wallet/market/market_ui.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Replaced base::make_span() with base::span().
  5. browser/ui/webui/brave_wallet/nft/nft_ui.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Replaced base::make_span() with base::span().
  6. browser/ui/webui/brave_wallet/trezor/trezor_ui.cc:

    • Replaced UNSAFE_TODO(base::make_span()) with base::span().
  7. browser/ui/webui/brave_wallet/wallet_page_ui.cc:

    • Replaced UNSAFE_TODO(base::make_span()) with base::span().
  8. browser/ui/webui/brave_wallet/wallet_panel_ui.cc:

    • Replaced UNSAFE_TODO(base::make_span()) with base::span().
  9. components/brave_wallet/browser/bitcoin/bitcoin_discover_account_task.cc and .h:

    • Removed #pragma allow_unsafe_buffers.
    • Replaced array with std::array.
  10. components/brave_wallet/browser/bitcoin/bitcoin_knapsack_solver_unittest.cc:

    • Updated to use base::as_byte_span().
  11. components/brave_wallet/browser/bitcoin/bitcoin_max_send_solver_unittest.cc:

    • Updated to use base::as_byte_span().
  12. components/brave_wallet/browser/eip1559_transaction.cc and .h:

    • Updated function signatures to use base::span.
    • Replaced std::vector<uint8_t> with KeccakHashArray in some places.
  13. components/brave_wallet/browser/eip1559_transaction_unittest.cc:

    • Updated test cases to use base::HexStringToSpan().
  14. components/brave_wallet/browser/eip2930_transaction.cc and .h:

    • Updated function signatures to use base::span.
    • Replaced std::vector<uint8_t> with KeccakHashArray in some places.
  15. components/brave_wallet/browser/eip2930_transaction_unittest.cc:

    • Updated test cases to use base::HexStringToSpan().
  16. components/brave_wallet/browser/ens_resolver_task.cc:

    • Updated to use base::span() and base::as_byte_span().
  17. components/brave_wallet/browser/eth_abi_decoder.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Updated to use base::SpanReader.
  18. components/brave_wallet/browser/eth_allowance_manager.cc:

    • Updated to use base::byte_span_from_cstring().
  19. components/brave_wallet/browser/eth_data_builder.cc and _unittest.cc:

    • Updated to use base::span().
  20. components/brave_wallet/browser/eth_gas_utils.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Replaced C-style arrays with std::array.
  21. components/brave_wallet/browser/eth_topics_builder.cc:

    • Updated to use base::byte_span_from_cstring().
  22. components/brave_wallet/browser/eth_transaction.cc and .h:

    • Updated function signatures to use base::span.
    • Replaced std::vector<uint8_t> with KeccakHashArray in some places.
  23. components/brave_wallet/browser/eth_transaction_unittest.cc:

    • Updated test cases to use base::HexStringToSpan().
  24. components/brave_wallet/browser/eth_tx_manager.cc:

    • Updated to use HexEncodeLower().
  25. components/brave_wallet/browser/ethereum_keyring.cc and .h:

    • Updated function signatures to use base::span.
    • Replaced std::vector<uint8_t> with fixed-size arrays in some places.
  26. components/brave_wallet/browser/ethereum_keyring_unittest.cc:

    • Updated test cases to use base::HexStringToSpan().
  27. components/brave_wallet/browser/filecoin_keyring.cc:

    • Updated to use base::span().
  28. components/brave_wallet/browser/internal/hd_key.cc and .h:

    • Significant refactoring to use safer buffer handling.
    • Replaced std::vector<uint8_t> with fixed-size arrays in many places.
    • Updated function signatures to use base::span.
  29. components/brave_wallet/browser/internal/hd_key_unittest.cc:

    • Updated test cases to use base::HexStringToSpan().
  30. components/brave_wallet/browser/json_rpc_service_unittest.cc:

    • Updated to use base::span().
  31. components/brave_wallet/browser/keyring_service.cc and .h:

    • Updated function signatures to use base::span.
  32. components/brave_wallet/browser/keyring_service_migrations.cc:

    • Updated to use base::span().
  33. components/brave_wallet/browser/meld_integration_response_parser_unittest.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Updated test cases to use range-based for loops.
  34. components/brave_wallet/browser/password_encryptor_unittest.cc:

    • Updated to use base::as_byte_span().
  35. components/brave_wallet/browser/permission_utils_unittest.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Updated test cases to use range-based for loops.
  36. components/brave_wallet/browser/rlp_encode.cc and .h:

    • Significant refactoring to use safer buffer handling.
    • Updated function signatures to return std::vector<uint8_t> instead of std::string.
  37. components/brave_wallet/browser/rlp_encode_unittest.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Updated test cases to use RLPTestStringToValue().
  38. components/brave_wallet/browser/secp256k1_hd_keyring.cc:

    • Updated to use base::span().
  39. components/brave_wallet/browser/sns_resolver_task.cc:

    • Updated to use base::span() and base::as_byte_span().
  40. components/brave_wallet/browser/solana_instruction_builder.cc:

    • Removed #pragma allow_unsafe_buffers.
    • Updated to use base::span() and base::SpanWriter.
  41. components/brave_wallet/browser/solana_message.cc:

    • Updated to use base::span().
  42. components/brave_wallet/browser/solana_message_address_table_lookup.cc:

    • Updated to use base::span().
  43. components/brave_wallet/browser/wallet_data_files_installer.cc:

    • Replaced UNSAFE_TODO() with direct assignment.
  44. components

@supermassive
Copy link
Collaborator Author

Would it be possible to break apart this PR into smaller separate PRs that are more manageable to review? These are more than mechanical changes, and I feel we could be missing things due to the sheer size of it.

I understand the pain of reviewing this PR and it would be worth making these changes incremental from start. But I'm afraid that would consume too much time redoing it now.

Copy link
Member

@kdenhartog kdenhartog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall LGTM - removing sec-review label

@@ -3,12 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#ifdef UNSAFE_BUFFERS_BUILD
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: did we not have anything to fix in this one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what happened. Maybe corresponding included header triggered warnings

return RLPTestStringToValue(s, &left_over);
base::Value RLPTestStringToValue(std::string s) {
base::ReplaceChars(s, "'", "\"", &s);
return base::test::ParseJson(s);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice refactor

@kdenhartog kdenhartog removed their assignment Nov 5, 2024
@cdesouza-chromium
Copy link
Collaborator

Would it be possible to break apart this PR into smaller separate PRs that are more manageable to review? These are more than mechanical changes, and I feel we could be missing things due to the sheer size of it.

I understand the pain of reviewing this PR and it would be worth making these changes incremental from start. But I'm afraid that would consume too much time redoing it now.

I think we need to be a bit sensitive to reviewers time and bandwidth in digesting a problem. I don't think I can reasonably review this PR the state it is.

@supermassive supermassive merged commit e840557 into master Nov 6, 2024
18 of 19 checks passed
@supermassive supermassive deleted the fix_unsafe_todo branch November 6, 2024 04:38
@github-actions github-actions bot added this to the 1.73.x - Nightly milestone Nov 6, 2024
@brave-builds
Copy link
Collaborator

Released in v1.73.78

@@ -42,6 +38,13 @@
using crypto::Encryptor;
using crypto::SymmetricKey;

namespace base {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely not something we should be doing. You're effectively creating a layering violation with a kind of backdoor chromium src override for base.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I basically wanted instances of this

template <size_t N>
struct SecureByteArray : public std::array<uint8_t, N> {
  ~SecureByteArray() { crypto::internal::SecureZeroBuffer(base::span(*this)); }
};

to be implicitly convertible to fixed size spans.

Will think how to achieve this in a different but succinct way.

cdesouza-chromium added a commit that referenced this pull request Nov 6, 2024
cdesouza-chromium added a commit that referenced this pull request Nov 6, 2024
This reverts commit e840557.

The original PR introduces a specialisation to `base::internal` that
is not allowed, and would be Undefined Behaviour with `std::span`. This
has broken `cr132`.
secp256k1_pubkey public_key;
if (!secp256k1_ec_pubkey_create(GetSecp256k1Ctx(), &public_key,
private_key.data())) {
LOG(ERROR) << "secp256k1_ec_pubkey_create failed";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most logging should be removed before merge and at the very least this should be VLOG instead of error logs. Also using a log in place of returning actual error information using base::expected is an anti-pattern.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we don't need this logging. This is just some moved code which I didn't want to change much

bridiver pushed a commit that referenced this pull request Nov 6, 2024
This reverts commit e840557.

The original PR introduces a specialisation to `base::internal` that
is not allowed, and would be Undefined Behaviour with `std::span`. This
has broken `cr132`.
@bsclifton bsclifton modified the milestones: 1.73.x - Nightly, 1.74.x - Nightly Nov 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix -Wunsafe-buffer-usage exclusions for wallet files
9 participants