Skip to content

<format>: Misbehavior for huge strings #4479

@StephanTLavavej

Description

@StephanTLavavej

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***]

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