diff --git a/src/String.h b/src/String.h index 2dadae7..684c49c 100644 --- a/src/String.h +++ b/src/String.h @@ -121,18 +121,20 @@ public: } bool toInt(int& v) const { + if (mLen <= 0 || !mDat) { + return false; + } v = 0; int i = 0; int sign = 1; - if (i > 0) { - if (mDat[0] == '+') { - ++i; - } else if (mDat[0] == '+') { - sign = -1; - ++i; - } else { - return false; - } + if (mDat[0] == '+') { + ++i; + } else if (mDat[0] == '-') { + sign = -1; + ++i; + } + if (i >= mLen) { + return false; } for ( ; i < mLen; ++i) { if (mDat[i] >= '0' && mDat[i] <= '9') { diff --git a/test/run.sh b/test/run.sh index 3ff441e..7a34a92 100755 --- a/test/run.sh +++ b/test/run.sh @@ -149,6 +149,7 @@ TESTS=( "test/logunit_vsnprintf.py" "test/logger_thread_init.py" "test/logger_unbounded_logunit.py" + "test/string_to_int.py" "test/pubsub_long_name.py" "test/pubsub_large_message.py" "test/transaction_forbid.py" diff --git a/test/string_to_int.cpp b/test/string_to_int.cpp new file mode 100644 index 0000000..03f7388 --- /dev/null +++ b/test/string_to_int.cpp @@ -0,0 +1,49 @@ +/* + * Verify String::toInt handles signed values. + */ + +#include "../src/String.h" + +int main() { + int v = 0; + { + String s("+1", 2); + bool ok = s.toInt(v); + if (!ok || v != 1) { + fprintf(stderr, "toInt(+1) ok=%d v=%d len=%d dat=%c%c\n", + (int)ok, v, s.length(), + s.data() ? s.data()[0] : '?', + s.data() ? s.data()[1] : '?'); + return 1; + } + } + { + bool ok = String("-1", 2).toInt(v); + if (!ok || v != -1) { + fprintf(stderr, "toInt(-1) ok=%d v=%d\n", (int)ok, v); + return 2; + } + } + { + bool ok = String("0", 1).toInt(v); + if (!ok || v != 0) { + fprintf(stderr, "toInt(0) ok=%d v=%d\n", (int)ok, v); + return 3; + } + } + { + bool ok = String("+", 1).toInt(v); + if (ok) { + fprintf(stderr, "toInt(+) ok=%d v=%d\n", (int)ok, v); + return 4; + } + } + { + bool ok = String("-", 1).toInt(v); + if (ok) { + fprintf(stderr, "toInt(-) ok=%d v=%d\n", (int)ok, v); + return 5; + } + } + return 0; +} diff --git a/test/string_to_int.py b/test/string_to_int.py new file mode 100644 index 0000000..8cc8529 --- /dev/null +++ b/test/string_to_int.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# +# Build and run the String::toInt sign handling test. +# + +import os +import subprocess +import tempfile +from test_util import parse_args, exit_with_result + + +def run_test(project_root): + src = os.path.join(project_root, "test", "string_to_int.cpp") + if not os.path.exists(src): + print("FAIL: string_to_int.cpp not found") + return False + + with tempfile.TemporaryDirectory() as tmp: + exe = os.path.join(tmp, "string_to_int") + cmd = [ + "g++", + "-std=c++11", + src, + "-o", + exe, + ] + try: + subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except Exception as exc: + print("FAIL: compile string_to_int:", exc) + return False + try: + subprocess.check_call([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as exc: + print("FAIL: string_to_int returned", exc.returncode) + return False + return True + + +if __name__ == "__main__": + _ = parse_args("String toInt test") + root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + success = run_test(root) + exit_with_result(success, "string toInt", "string toInt")