Unidata / UDUNITS-2

API and utility for arithmetic manipulation of units of physical quantities
http://www.unidata.ucar.edu/software/udunits
Other
59 stars 36 forks source link

utlex: signed integer overflow #91

Closed schwehr closed 3 years ago

schwehr commented 4 years ago

To report a non-security related issue, please provide:

8fb0b21826a9abcd36e097bd1cb8c95c947b9526

linux - custom env

scanner.l:213:11: runtime error: signed integer overflow: 451044104 * 10 cannot be represented in type 'int'
    #0 0x5593d4c827d0 in utlex scanner.l:213:11
    #1 0x5593d4c7b883 in utparse parser.c:1394:16
    #2 0x5593d4c7e35f in ut_parse parser.y:656:17
    #3 0x5593d4c7039d in LLVMFuzzerTestOneInput third_party/udunits/fuzzers/ut_parse_fuzzer.cc:27:19

testcase-5578514623365120.zip

Fix is along the lines of:

#include <limits.h>

// SNIP
    if (exponent > INT_MAX/10) {
        status = ERR;
        break;
    }
    exponent *= 10;

Using

#include <stddef.h>
#include <stdint.h>

#include <string>
#include <vector>

#include "base/logging.h"
#include "third_party/absl/cleanup/cleanup.h"
#include "third_party/udunits/lib/udunits2.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  const std::string data2(reinterpret_cast<const char *>(data), size);

  // Load the xml units config.
  ut_system *unit_system_from_xml = ut_read_xml(nullptr);
  CHECK_NE(nullptr, unit_system_from_xml);
  auto unit_system_from_xml_cleaner = absl::MakeCleanup(
      [unit_system_from_xml] { ut_free_system(unit_system_from_xml); });

  ut_set_error_message_handler(ut_ignore);

  ut_system *unit_system = ut_new_system();
  CHECK_NE(nullptr, unit_system);
  auto unit_system_cleaner =
      absl::MakeCleanup([unit_system] { ut_free_system(unit_system); });

  ut_unit *unit = ut_parse(unit_system, data2.c_str(), UT_ASCII);
  if (unit == nullptr) return 0;
  auto unit_cleaner = absl::MakeCleanup([unit] { ut_free(unit); });

  constexpr size_t kBufSize = 1000;
  std::vector<char> buf(kBufSize);
  CHECK_GE(static_cast<int>(kBufSize), ut_format(unit, &buf[0], kBufSize, 0));

  return 0;
}
semmerson commented 3 years ago

Added. It'll be in the next release.

Thanks Kurt.