warthog-network / Warthog

Experimental cryptocurrency implementation
MIT License
21 stars 13 forks source link

Comprehensive Code Review - Addressing Bugs, Errors, and Potential Security Issues #60

Closed Adefebrian closed 1 month ago

Adefebrian commented 1 month ago

Description: Hey team! 🚀 After diving deep into the codebase, I’ve identified a series of bugs, potential errors, and some areas that could open us up to security risks. These issues span across multiple files, including the ChainServer, Config, and Wallet classes. Let’s break down what I found and how we can tighten things up:

1. File Existence Check in save() Method

2. Exception Handling in open_wallet()

3. Inconsistent Error Messages

4. Logical Errors in Wallet Constructor

5. Exception-Safety in process() Function

6. Incomplete Initialization Check

7. Potentially Unsafe auto Type in read_amount()

8. Potential Buffer Overflow in read_with_msg()

9. Lack of Command-Line Arguments Validation

10. Undefined Behavior with CompactUInt::compact()

11. Inconsistent assert() Usage

12. Incomplete Error Handling in endpoint.send_transaction()


Steps to Fix:

  1. File Existence Check: Implement atomic operations or retry mechanisms in save() to handle race conditions.
  2. Exception Handling: Add a catch-all handler in open_wallet() to catch unexpected exceptions.
  3. Standardize Error Messages: Update error messages across the codebase for consistency.
  4. Wallet Constructor: Improve error messaging with more detail and logging.
  5. RAII Implementation: Refactor the process() function to use RAII or ensure proper resource cleanup.
  6. Initialization Check: Validate ai.file_arg before using it in the process() function.
  7. Type Safety: Define the type of balance_lambda explicitly in read_amount().
  8. Input Safety: Use std::getline in read_with_msg() to prevent buffer overflows.
  9. Argument Validation: Add additional validation checks for command-line arguments in process().
  10. CompactUInt Handling: Ensure CompactUInt::compact() correctly handles list initialization.
  11. Assert Replacement: Replace assert() with runtime checks in process().
  12. Error Handling: Improve error handling in endpoint.send_transaction().

Environment:


Let’s get these issues ironed out to make our codebase stronger, safer, and more reliable. 💪 If you have any questions or need further details, feel free to reach out!

ByPumbaa commented 1 month ago

Thank you:

  1. There is no atomic way to block file creation or deletion across different file systems. The check is sufficiently good. Furthermore it does not make sense to do repeated checks: When the file does not exist and we are good to write why check again? And even if we checked again the problem that a new file could be created is still present between the last check and the file write. So both your solutions a) atomicity and b) repeated check are not possible or do not make sense.
  2. Yes we can change that.
  3. Please specify the line and file of messages you like to change.
  4. We can write inconsistent wallet data. This will only be triggered if the wallet file is changed by someone and there is no point detailing which consistency check failed.
  5. You are wrong, every object created is RAII itself, on exceptions the stack unwinds and every destructor is called. No leak possible. If you don't agree please specify which variable you think leaks memory on exception.
  6. The ai argument for the process() function is filled by an auto generated function (read about https://www.gnu.org/software/gengetopt/gengetopt.html). This is proven software and the output should be valid.
  7. No, the balance_lambda is a lambda variable. You cannot specify a type, every lambda has its own implicit unique type. Your comment does not make sense.
  8. This is wrong, no overflow is possible in operator>>(std::istream&, std::string&).
  9. See 6. It is fine to assume that command-line arguments are correctly validated by the auto-generated argument parser because gengetopt is proven software.
  10. You are wrong saying " list-initialized Funds", brace initialization is used. You say "but it’s unclear if this method can handle list initialization.". It is clear from the function declaration. No list initialization used. No issue here. We can remove the braces to avoid an unnecessary temporary object (which is actually optimized away anyway).
  11. The assert is good and should be there. We use assert where we assume that something holds and to crash the program when we were wrong. This should be a crash and not a user reported error to reflect the fact that this should NEVER happen.
  12. Nothing is "destructed into ..." We use structured binding to report both, error code and error message as returned by the node. When there is an empty error message we print an empty error message. I see no problem here. We just report what we got from the node API.

Please make it clear when you use AI and post rather on Discord than opening an issue. Furthermore, for real issues address them separately. I will close this now.