1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "base/strings/stringprintf.h"
11
12 #include <errno.h>
13 #include <stddef.h>
14
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19
20 namespace {
21
22 // A helper for the StringAppendV test that follows.
23 //
24 // Just forwards its args to StringAppendV.
25 template <class CharT>
StringAppendVTestHelper(std::basic_string<CharT> * out,const CharT * format,...)26 static void StringAppendVTestHelper(std::basic_string<CharT>* out,
27 const CharT* format,
28 ...) {
29 va_list ap;
30 va_start(ap, format);
31 StringAppendV(out, format, ap);
32 va_end(ap);
33 }
34
35 } // namespace
36
TEST(StringPrintfTest,StringPrintfEmpty)37 TEST(StringPrintfTest, StringPrintfEmpty) {
38 EXPECT_EQ("", StringPrintf("%s", ""));
39 }
40
TEST(StringPrintfTest,StringPrintfMisc)41 TEST(StringPrintfTest, StringPrintfMisc) {
42 EXPECT_EQ("123hello w", StringPrintf("%3d%2s %1c", 123, "hello", 'w'));
43 }
44
TEST(StringPrintfTest,StringAppendfEmptyString)45 TEST(StringPrintfTest, StringAppendfEmptyString) {
46 std::string value("Hello");
47 StringAppendF(&value, "%s", "");
48 EXPECT_EQ("Hello", value);
49 }
50
TEST(StringPrintfTest,StringAppendfString)51 TEST(StringPrintfTest, StringAppendfString) {
52 std::string value("Hello");
53 StringAppendF(&value, " %s", "World");
54 EXPECT_EQ("Hello World", value);
55 }
56
TEST(StringPrintfTest,StringAppendfInt)57 TEST(StringPrintfTest, StringAppendfInt) {
58 std::string value("Hello");
59 StringAppendF(&value, " %d", 123);
60 EXPECT_EQ("Hello 123", value);
61 }
62
63 // Make sure that lengths exactly around the initial buffer size are handled
64 // correctly.
TEST(StringPrintfTest,StringPrintfBounds)65 TEST(StringPrintfTest, StringPrintfBounds) {
66 const int kSrcLen = 1026;
67 char src[kSrcLen];
68 std::fill_n(src, kSrcLen, 'A');
69
70 wchar_t srcw[kSrcLen];
71 std::fill_n(srcw, kSrcLen, 'A');
72
73 char16_t src16[kSrcLen];
74 std::fill_n(src16, kSrcLen, 'A');
75
76 for (int i = 1; i < 3; i++) {
77 src[kSrcLen - i] = 0;
78 std::string out;
79 EXPECT_EQ(src, StringPrintf("%s", src));
80 }
81 }
82
83 // Test very large sprintfs that will cause the buffer to grow.
TEST(StringPrintfTest,Grow)84 TEST(StringPrintfTest, Grow) {
85 char src[1026];
86 for (auto& i : src)
87 i = 'A';
88 src[1025] = 0;
89
90 const char fmt[] = "%sB%sB%sB%sB%sB%sB%s";
91
92 const int kRefSize = 320000;
93 char* ref = new char[kRefSize];
94 #if BUILDFLAG(IS_WIN)
95 sprintf_s(ref, kRefSize, fmt, src, src, src, src, src, src, src);
96 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
97 snprintf(ref, kRefSize, fmt, src, src, src, src, src, src, src);
98 #endif
99
100 EXPECT_EQ(ref, StringPrintf(fmt, src, src, src, src, src, src, src));
101 delete[] ref;
102 }
103
TEST(StringPrintfTest,StringAppendV)104 TEST(StringPrintfTest, StringAppendV) {
105 std::string out;
106 StringAppendVTestHelper(&out, "%d foo %s", 1, "bar");
107 EXPECT_EQ("1 foo bar", out);
108 }
109
110 // Test the boundary condition for the size of the string_util's
111 // internal buffer.
TEST(StringPrintfTest,GrowBoundary)112 TEST(StringPrintfTest, GrowBoundary) {
113 const int kStringUtilBufLen = 1024;
114 // Our buffer should be one larger than the size of StringAppendVT's stack
115 // buffer.
116 // And need extra one for NULL-terminator.
117 const int kBufLen = kStringUtilBufLen + 1 + 1;
118 char src[kBufLen];
119 for (int i = 0; i < kBufLen - 1; ++i)
120 src[i] = 'a';
121 src[kBufLen - 1] = 0;
122
123 EXPECT_EQ(src, StringPrintf("%s", src));
124 }
125
126 // Test that StringPrintf and StringAppendV do not change errno.
TEST(StringPrintfTest,StringPrintfErrno)127 TEST(StringPrintfTest, StringPrintfErrno) {
128 errno = 1;
129 EXPECT_EQ("", StringPrintf("%s", ""));
130 EXPECT_EQ(1, errno);
131 std::string out;
132 StringAppendVTestHelper(&out, "%d foo %s", 1, "bar");
133 EXPECT_EQ(1, errno);
134 }
135
136 } // namespace base
137