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 #include "partition_alloc/partition_alloc_base/strings/stringprintf.h"
6 
7 #include <cstdarg>
8 #include <cstdio>
9 
10 #include "partition_alloc/partition_alloc_base/compiler_specific.h"
11 #include "partition_alloc/partition_alloc_base/scoped_clear_last_error.h"
12 
13 namespace partition_alloc::internal::base {
14 
15 std::string PA_PRINTF_FORMAT(1, 2)
TruncatingStringPrintf(const char * format,...)16     TruncatingStringPrintf(const char* format, ...) {
17   base::ScopedClearLastError last_error;
18   char stack_buf[kMaxLengthOfTruncatingStringPrintfResult + 1];
19   va_list arguments;
20   va_start(arguments, format);
21 #if BUILDFLAG(IS_WIN)
22   int result = vsnprintf_s(stack_buf, std::size(stack_buf), _TRUNCATE, format,
23                            arguments);
24 #else
25   int result = vsnprintf(stack_buf, std::size(stack_buf), format, arguments);
26 #endif
27   va_end(arguments);
28 #if BUILDFLAG(IS_WIN)
29   // If an output error is encountered or data is larger than count,
30   // a negative value is returned. So to see whether an output error is really
31   // encountered or not, need to see errno. If errno == EINVAL or
32   // errno == ERANGE, an output error is encountered. If not, an output is
33   // just truncated.
34   if (result < 0 && (errno == EINVAL || errno == ERANGE)) {
35     return std::string();
36   }
37 #else
38   // If an output error is encountered, a negative value is returned.
39   // In the case, return an empty string.
40   if (result < 0) {
41     return std::string();
42   }
43 #endif
44   // If result is equal or larger than std::size(stack_buf), the output was
45   // truncated. ::base::StringPrintf doesn't truncate output.
46   return std::string(stack_buf);
47 }
48 
49 }  // namespace partition_alloc::internal::base
50