Skip to content

<format>: Misbehavior for huge strings #4479

Description

Noticed while reviewing #4438, but affects main. I don't see any Standardese allowing us to assume that sizes and widths can fit in an int.

D:\GitHub\STL\out\x64>type meow.cpp
#include <cassert>
#include <chrono>
#include <cstddef>
#include <format>
#include <print>
#include <string>
#include <string_view>
#include <tuple>
using namespace std;

static_assert(sizeof(void*) == 8, "This test requires 64-bit.");

void test_string(const size_t n) {
    const auto start = chrono::steady_clock::now();

    const string str(n, 'X');

    {
        const string result = format("{}", str);
        assert(result.size() == n);
        assert(result == str);
    }

    {
        const string result = format("{:o^{}}", str, n + 4);
        assert(result.size() == n + 4);
        assert(result.starts_with("oo"));
        assert(string_view{result}.substr(2, n) == str);
        assert(result.ends_with("oo"));
    }

    const auto finish  = chrono::steady_clock::now();
    const auto elapsed = chrono::duration_cast<chrono::seconds>(finish - start);

    println("test_string({}) passed, {} elapsed.", n, elapsed);
}

#ifdef TEST_TUPLE
void test_tuple(const size_t n) {
    const auto start = chrono::steady_clock::now();

    tuple<string> t;
    get<0>(t).resize(n, 'X');

    {
        const string result = format("{}", t);
        assert(result.size() == n + 4);
        assert(result.starts_with("(\""));
        assert(string_view{result}.substr(2, n) == get<0>(t));
        assert(result.ends_with("\")"));
    }

    {
        const string result = format("{:o^{}}", t, n + 8);
        assert(result.size() == n + 8);
        assert(result.starts_with("oo(\""));
        assert(string_view{result}.substr(4, n) == get<0>(t));
        assert(result.ends_with("\")oo"));
    }

    const auto finish  = chrono::steady_clock::now();
    const auto elapsed = chrono::duration_cast<chrono::seconds>(finish - start);

    println("test_tuple({}) passed, {} elapsed.", n, elapsed);
}
#endif // TEST_TUPLE

int main() {
    test_string(5);
    test_string(50'000'000);
    test_string(500'000'000);
    test_string(2'000'000'000);
    test_string(3'000'000'000);

#ifdef TEST_TUPLE
    test_tuple(5);
    test_tuple(50'000'000);
    test_tuple(500'000'000);
    test_tuple(2'000'000'000);
    test_tuple(3'000'000'000);
#endif // TEST_TUPLE
}
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W4 /std:c++latest /MT /O2 meow.cpp && meow
meow.cpp
test_string(5) passed, 0s elapsed.
test_string(50000000) passed, 1s elapsed.
test_string(500000000) passed, 14s elapsed.
test_string(2000000000) passed, 56s elapsed.
[***SILENT CRASH***]

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixedSomething works now, yay!formatC++20/23 format

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions