summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibC/scanf.cpp
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2021-04-04 03:01:43 +0430
committerAndreas Kling <kling@serenityos.org>2021-04-04 00:40:41 +0200
commit143c68755bd02da1c6b0091025ebe5fe27d93f67 (patch)
treea91feefe443d0e36b2c93b295d73972a82193686 /Userland/Libraries/LibC/scanf.cpp
parentf05cca7a9a4f4206f68b0f5d029b7c09293816d9 (diff)
downloadserenity-143c68755bd02da1c6b0091025ebe5fe27d93f67.zip
LibC: Use 'long long' specialisations of scanf's read_element_concrete
...for 'long long' and 'unsigned long long', instead of reading them as 'long's and 'unsigned long's. Also add a test for values that can only fit in (unsigned) long long. Fixes #6096.
Diffstat (limited to 'Userland/Libraries/LibC/scanf.cpp')
-rw-r--r--Userland/Libraries/LibC/scanf.cpp42
1 files changed, 38 insertions, 4 deletions
diff --git a/Userland/Libraries/LibC/scanf.cpp b/Userland/Libraries/LibC/scanf.cpp
index 7e517c970c..aae825a426 100644
--- a/Userland/Libraries/LibC/scanf.cpp
+++ b/Userland/Libraries/LibC/scanf.cpp
@@ -164,6 +164,40 @@ struct read_element_concrete<unsigned, ApT, kind> {
};
template<typename ApT, ReadKind kind>
+struct read_element_concrete<long long, ApT, kind> {
+ bool operator()(GenericLexer& lexer, va_list* ap)
+ {
+ lexer.ignore_while(isspace);
+
+ auto* ptr = va_arg(*ap, ApT*);
+ long long value = 0;
+ char* endptr = nullptr;
+ auto nptr = lexer.remaining().characters_without_null_termination();
+ if constexpr (kind == ReadKind::Normal)
+ value = strtoll(nptr, &endptr, 10);
+ if constexpr (kind == ReadKind::Octal)
+ value = strtoll(nptr, &endptr, 8);
+ if constexpr (kind == ReadKind::Hex)
+ value = strtoll(nptr, &endptr, 16);
+ if constexpr (kind == ReadKind::Infer)
+ value = strtoll(nptr, &endptr, 0);
+
+ if (!endptr)
+ return false;
+
+ if (endptr == nptr)
+ return false;
+
+ auto diff = endptr - nptr;
+ VERIFY(diff > 0);
+ lexer.ignore((size_t)diff);
+
+ *ptr = value;
+ return true;
+ }
+};
+
+template<typename ApT, ReadKind kind>
struct read_element_concrete<unsigned long long, ApT, kind> {
bool operator()(GenericLexer& lexer, va_list* ap)
{
@@ -248,15 +282,15 @@ struct read_element {
if constexpr (IsSame<T, unsigned>::value)
return read_element_concrete<T, unsigned, kind> {}(input_lexer, ap);
if constexpr (IsSame<T, float>::value)
- return read_element_concrete<T, double, kind> {}(input_lexer, ap);
+ return read_element_concrete<int, double, kind> {}(input_lexer, ap);
return false;
case LongLong:
if constexpr (IsSame<T, int>::value)
- return read_element_concrete<T, long long, kind> {}(input_lexer, ap);
+ return read_element_concrete<long long, long long, kind> {}(input_lexer, ap);
if constexpr (IsSame<T, unsigned>::value)
- return read_element_concrete<T, unsigned long long, kind> {}(input_lexer, ap);
+ return read_element_concrete<unsigned long long, unsigned long long, kind> {}(input_lexer, ap);
if constexpr (IsSame<T, float>::value)
- return read_element_concrete<T, double, kind> {}(input_lexer, ap);
+ return read_element_concrete<long long, double, kind> {}(input_lexer, ap);
return false;
case IntMax:
return read_element_concrete<T, intmax_t, kind> {}(input_lexer, ap);