crypto-chassis / ccapi

A header-only C++ library for interacting with crypto exchanges. Bindings for Python, Java, C#, Go, and Javascript are provided.
https://discord.gg/b5EKcp9s8T
MIT License
582 stars 201 forks source link

fix two bugs about computeHash and roundInputBySignificantFigure #480

Open cloudQuant opened 1 week ago

cloudQuant commented 1 week ago

when the shaVersion is not right, it will generate memory leak, we need free the context in the default

static std::string computeHash(const ShaVersion shaVersion, const std::string& unhashed, bool returnHex = false) {
    EVP_MD_CTX* context = EVP_MD_CTX_new();
    switch (shaVersion) {
      case ShaVersion::SHA256:
        EVP_DigestInit_ex(context, EVP_sha256(), nullptr);
        break;
      case ShaVersion::SHA512:
        EVP_DigestInit_ex(context, EVP_sha512(), nullptr);
        break;
      default:
        EVP_MD_CTX_free(context);  // Release the context, adding an extra line here to avoid potential memory leaks that may occur in computeHash
        throw std::invalid_argument("invalid shaVersion");
    }
    EVP_DigestUpdate(context, unhashed.c_str(), unhashed.length());
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned int lengthOfHash = 0;
    EVP_DigestFinal_ex(context, hash, &lengthOfHash);
    EVP_MD_CTX_free(context);
    std::stringstream ss;
    if (returnHex) {
      for (unsigned int i = 0; i < lengthOfHash; ++i) {
        ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
      }
    } else {
      for (unsigned int i = 0; i < lengthOfHash; ++i) {
        ss << (char)hash[i];
      }
    }
    return ss.str();
  }

the original function : roundInputBySignificantFigure(0.00123456, 3, 1), output is "000.124" maybe we expect the output is "0.00124", so we need to modify three line in else new function will output "0.00124"

static std::string roundInputBySignificantFigure(double input, int numSignificantFigure, int roundDirection) {
    const auto& splitted = UtilString::split(UtilString::printDoubleScientific(input), 'e');
    double a = std::stod(splitted.at(0)) * std::pow(10, numSignificantFigure - 1);
    double b;
    if (roundDirection > 0) {
      b = std::ceil(a);
    } else if (roundDirection < 0) {
      b = std::floor(a);
    } else {
      b = std::round(a);
    }
    std::string c = std::to_string(static_cast<int>(b));
    int exponent = std::stoi(splitted.at(1)) - (numSignificantFigure - 1);
    std::string output;
    if (exponent >= 0) {
      output = c + std::string(exponent, '0');
    } else if (-exponent <= c.size() - 1) {
      output = c.substr(0, c.size() + exponent);
      output += ".";
      output += c.substr(c.size() + exponent);
    } else {
//      output = std::string(-exponent - c.size() + 1, '0');
//      output += ".";
//      output += c;  // use these three code, roundInputBySignificantFigure(0.00123456, 3, 1), output is  "000.124"
      output = "0.";
      output += std::string(-exponent - c.size(), '0');
      output += c;   // use these three code, roundInputBySignificantFigure(0.00123456, 3, 1), output is  "0.00124"
    }
    return output;
  }