1// Copyright 2013 The Chromium Authors. All rights reserved. 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 "base/strings/safe_sprintf.h" 6 7#include <errno.h> 8#include <string.h> 9 10#include <limits> 11 12#include "base/macros.h" 13#include "build/build_config.h" 14 15#if !defined(NDEBUG) 16// In debug builds, we use RAW_CHECK() to print useful error messages, if 17// SafeSPrintf() is called with broken arguments. 18// As our contract promises that SafeSPrintf() can be called from any 19// restricted run-time context, it is not actually safe to call logging 20// functions from it; and we only ever do so for debug builds and hope for the 21// best. We should _never_ call any logging function other than RAW_CHECK(), 22// and we should _never_ include any logging code that is active in production 23// builds. Most notably, we should not include these logging functions in 24// unofficial release builds, even though those builds would otherwise have 25// DCHECKS() enabled. 26// In other words; please do not remove the #ifdef around this #include. 27// Instead, in production builds we opt for returning a degraded result, 28// whenever an error is encountered. 29// E.g. The broken function call 30// SafeSPrintf("errno = %d (%x)", errno, strerror(errno)) 31// will print something like 32// errno = 13, (%x) 33// instead of 34// errno = 13 (Access denied) 35// In most of the anticipated use cases, that's probably the preferred 36// behavior. 37#include "base/logging.h" 38#define DEBUG_CHECK RAW_CHECK 39#else 40#define DEBUG_CHECK(x) do { if (x) { } } while (0) 41#endif 42 43namespace base { 44namespace strings { 45 46// The code in this file is extremely careful to be async-signal-safe. 47// 48// Most obviously, we avoid calling any code that could dynamically allocate 49// memory. Doing so would almost certainly result in bugs and dead-locks. 50// We also avoid calling any other STL functions that could have unintended 51// side-effects involving memory allocation or access to other shared 52// resources. 53// 54// But on top of that, we also avoid calling other library functions, as many 55// of them have the side-effect of calling getenv() (in order to deal with 56// localization) or accessing errno. The latter sounds benign, but there are 57// several execution contexts where it isn't even possible to safely read let 58// alone write errno. 59// 60// The stated design goal of the SafeSPrintf() function is that it can be 61// called from any context that can safely call C or C++ code (i.e. anything 62// that doesn't require assembly code). 63// 64// For a brief overview of some but not all of the issues with async-signal- 65// safety, refer to: 66// http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html 67 68namespace { 69const size_t kSSizeMaxConst = ((size_t)(ssize_t)-1) >> 1; 70 71const char kUpCaseHexDigits[] = "0123456789ABCDEF"; 72const char kDownCaseHexDigits[] = "0123456789abcdef"; 73} 74 75#if defined(NDEBUG) 76// We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(), 77// but C++ doesn't allow us to do that for constants. Instead, we have to 78// use careful casting and shifting. We later use a static_assert to 79// verify that this worked correctly. 80namespace { 81const size_t kSSizeMax = kSSizeMaxConst; 82} 83#else // defined(NDEBUG) 84// For efficiency, we really need kSSizeMax to be a constant. But for unit 85// tests, it should be adjustable. This allows us to verify edge cases without 86// having to fill the entire available address space. As a compromise, we make 87// kSSizeMax adjustable in debug builds, and then only compile that particular 88// part of the unit test in debug builds. 89namespace { 90static size_t kSSizeMax = kSSizeMaxConst; 91} 92 93namespace internal { 94void SetSafeSPrintfSSizeMaxForTest(size_t max) { 95 kSSizeMax = max; 96} 97 98size_t GetSafeSPrintfSSizeMaxForTest() { 99 return kSSizeMax; 100} 101} 102#endif // defined(NDEBUG) 103 104namespace { 105class Buffer { 106 public: 107 // |buffer| is caller-allocated storage that SafeSPrintf() writes to. It 108 // has |size| bytes of writable storage. It is the caller's responsibility 109 // to ensure that the buffer is at least one byte in size, so that it fits 110 // the trailing NUL that will be added by the destructor. The buffer also 111 // must be smaller or equal to kSSizeMax in size. 112 Buffer(char* buffer, size_t size) 113 : buffer_(buffer), 114 size_(size - 1), // Account for trailing NUL byte 115 count_(0) { 116// MSVS2013's standard library doesn't mark max() as constexpr yet. cl.exe 117// supports static_cast but doesn't really implement constexpr yet so it doesn't 118// complain, but clang does. 119#if __cplusplus >= 201103 && !(defined(__clang__) && defined(OS_WIN)) 120 static_assert(kSSizeMaxConst == 121 static_cast<size_t>(std::numeric_limits<ssize_t>::max()), 122 "kSSizeMaxConst should be the max value of an ssize_t"); 123#endif 124 DEBUG_CHECK(size > 0); 125 DEBUG_CHECK(size <= kSSizeMax); 126 } 127 128 ~Buffer() { 129 // The code calling the constructor guaranteed that there was enough space 130 // to store a trailing NUL -- and in debug builds, we are actually 131 // verifying this with DEBUG_CHECK()s in the constructor. So, we can 132 // always unconditionally write the NUL byte in the destructor. We do not 133 // need to adjust the count_, as SafeSPrintf() copies snprintf() in not 134 // including the NUL byte in its return code. 135 *GetInsertionPoint() = '\000'; 136 } 137 138 // Returns true, iff the buffer is filled all the way to |kSSizeMax-1|. The 139 // caller can now stop adding more data, as GetCount() has reached its 140 // maximum possible value. 141 inline bool OutOfAddressableSpace() const { 142 return count_ == static_cast<size_t>(kSSizeMax - 1); 143 } 144 145 // Returns the number of bytes that would have been emitted to |buffer_| 146 // if it was sized sufficiently large. This number can be larger than 147 // |size_|, if the caller provided an insufficiently large output buffer. 148 // But it will never be bigger than |kSSizeMax-1|. 149 inline ssize_t GetCount() const { 150 DEBUG_CHECK(count_ < kSSizeMax); 151 return static_cast<ssize_t>(count_); 152 } 153 154 // Emits one |ch| character into the |buffer_| and updates the |count_| of 155 // characters that are currently supposed to be in the buffer. 156 // Returns "false", iff the buffer was already full. 157 // N.B. |count_| increases even if no characters have been written. This is 158 // needed so that GetCount() can return the number of bytes that should 159 // have been allocated for the |buffer_|. 160 inline bool Out(char ch) { 161 if (size_ >= 1 && count_ < size_) { 162 buffer_[count_] = ch; 163 return IncrementCountByOne(); 164 } 165 // |count_| still needs to be updated, even if the buffer has been 166 // filled completely. This allows SafeSPrintf() to return the number of 167 // bytes that should have been emitted. 168 IncrementCountByOne(); 169 return false; 170 } 171 172 // Inserts |padding|-|len| bytes worth of padding into the |buffer_|. 173 // |count_| will also be incremented by the number of bytes that were meant 174 // to be emitted. The |pad| character is typically either a ' ' space 175 // or a '0' zero, but other non-NUL values are legal. 176 // Returns "false", iff the the |buffer_| filled up (i.e. |count_| 177 // overflowed |size_|) at any time during padding. 178 inline bool Pad(char pad, size_t padding, size_t len) { 179 DEBUG_CHECK(pad); 180 DEBUG_CHECK(padding <= kSSizeMax); 181 for (; padding > len; --padding) { 182 if (!Out(pad)) { 183 if (--padding) { 184 IncrementCount(padding-len); 185 } 186 return false; 187 } 188 } 189 return true; 190 } 191 192 // POSIX doesn't define any async-signal-safe function for converting 193 // an integer to ASCII. Define our own version. 194 // 195 // This also gives us the ability to make the function a little more 196 // powerful and have it deal with |padding|, with truncation, and with 197 // predicting the length of the untruncated output. 198 // 199 // IToASCII() converts an integer |i| to ASCII. 200 // 201 // Unlike similar functions in the standard C library, it never appends a 202 // NUL character. This is left for the caller to do. 203 // 204 // While the function signature takes a signed int64_t, the code decides at 205 // run-time whether to treat the argument as signed (int64_t) or as unsigned 206 // (uint64_t) based on the value of |sign|. 207 // 208 // It supports |base|s 2 through 16. Only a |base| of 10 is allowed to have 209 // a |sign|. Otherwise, |i| is treated as unsigned. 210 // 211 // For bases larger than 10, |upcase| decides whether lower-case or upper- 212 // case letters should be used to designate digits greater than 10. 213 // 214 // Padding can be done with either '0' zeros or ' ' spaces. Padding has to 215 // be positive and will always be applied to the left of the output. 216 // 217 // Prepends a |prefix| to the number (e.g. "0x"). This prefix goes to 218 // the left of |padding|, if |pad| is '0'; and to the right of |padding| 219 // if |pad| is ' '. 220 // 221 // Returns "false", if the |buffer_| overflowed at any time. 222 bool IToASCII(bool sign, bool upcase, int64_t i, int base, 223 char pad, size_t padding, const char* prefix); 224 225 private: 226 // Increments |count_| by |inc| unless this would cause |count_| to 227 // overflow |kSSizeMax-1|. Returns "false", iff an overflow was detected; 228 // it then clamps |count_| to |kSSizeMax-1|. 229 inline bool IncrementCount(size_t inc) { 230 // "inc" is either 1 or a "padding" value. Padding is clamped at 231 // run-time to at most kSSizeMax-1. So, we know that "inc" is always in 232 // the range 1..kSSizeMax-1. 233 // This allows us to compute "kSSizeMax - 1 - inc" without incurring any 234 // integer overflows. 235 DEBUG_CHECK(inc <= kSSizeMax - 1); 236 if (count_ > kSSizeMax - 1 - inc) { 237 count_ = kSSizeMax - 1; 238 return false; 239 } else { 240 count_ += inc; 241 return true; 242 } 243 } 244 245 // Convenience method for the common case of incrementing |count_| by one. 246 inline bool IncrementCountByOne() { 247 return IncrementCount(1); 248 } 249 250 // Return the current insertion point into the buffer. This is typically 251 // at |buffer_| + |count_|, but could be before that if truncation 252 // happened. It always points to one byte past the last byte that was 253 // successfully placed into the |buffer_|. 254 inline char* GetInsertionPoint() const { 255 size_t idx = count_; 256 if (idx > size_) { 257 idx = size_; 258 } 259 return buffer_ + idx; 260 } 261 262 // User-provided buffer that will receive the fully formatted output string. 263 char* buffer_; 264 265 // Number of bytes that are available in the buffer excluding the trailing 266 // NUL byte that will be added by the destructor. 267 const size_t size_; 268 269 // Number of bytes that would have been emitted to the buffer, if the buffer 270 // was sufficiently big. This number always excludes the trailing NUL byte 271 // and it is guaranteed to never grow bigger than kSSizeMax-1. 272 size_t count_; 273 274 DISALLOW_COPY_AND_ASSIGN(Buffer); 275}; 276 277 278bool Buffer::IToASCII(bool sign, bool upcase, int64_t i, int base, 279 char pad, size_t padding, const char* prefix) { 280 // Sanity check for parameters. None of these should ever fail, but see 281 // above for the rationale why we can't call CHECK(). 282 DEBUG_CHECK(base >= 2); 283 DEBUG_CHECK(base <= 16); 284 DEBUG_CHECK(!sign || base == 10); 285 DEBUG_CHECK(pad == '0' || pad == ' '); 286 DEBUG_CHECK(padding <= kSSizeMax); 287 DEBUG_CHECK(!(sign && prefix && *prefix)); 288 289 // Handle negative numbers, if the caller indicated that |i| should be 290 // treated as a signed number; otherwise treat |i| as unsigned (even if the 291 // MSB is set!) 292 // Details are tricky, because of limited data-types, but equivalent pseudo- 293 // code would look like: 294 // if (sign && i < 0) 295 // prefix = "-"; 296 // num = abs(i); 297 int minint = 0; 298 uint64_t num; 299 if (sign && i < 0) { 300 prefix = "-"; 301 302 // Turn our number positive. 303 if (i == std::numeric_limits<int64_t>::min()) { 304 // The most negative integer needs special treatment. 305 minint = 1; 306 num = static_cast<uint64_t>(-(i + 1)); 307 } else { 308 // "Normal" negative numbers are easy. 309 num = static_cast<uint64_t>(-i); 310 } 311 } else { 312 num = static_cast<uint64_t>(i); 313 } 314 315 // If padding with '0' zero, emit the prefix or '-' character now. Otherwise, 316 // make the prefix accessible in reverse order, so that we can later output 317 // it right between padding and the number. 318 // We cannot choose the easier approach of just reversing the number, as that 319 // fails in situations where we need to truncate numbers that have padding 320 // and/or prefixes. 321 const char* reverse_prefix = NULL; 322 if (prefix && *prefix) { 323 if (pad == '0') { 324 while (*prefix) { 325 if (padding) { 326 --padding; 327 } 328 Out(*prefix++); 329 } 330 prefix = NULL; 331 } else { 332 for (reverse_prefix = prefix; *reverse_prefix; ++reverse_prefix) { 333 } 334 } 335 } else 336 prefix = NULL; 337 const size_t prefix_length = reverse_prefix - prefix; 338 339 // Loop until we have converted the entire number. Output at least one 340 // character (i.e. '0'). 341 size_t start = count_; 342 size_t discarded = 0; 343 bool started = false; 344 do { 345 // Make sure there is still enough space left in our output buffer. 346 if (count_ >= size_) { 347 if (start < size_) { 348 // It is rare that we need to output a partial number. But if asked 349 // to do so, we will still make sure we output the correct number of 350 // leading digits. 351 // Since we are generating the digits in reverse order, we actually 352 // have to discard digits in the order that we have already emitted 353 // them. This is essentially equivalent to: 354 // memmove(buffer_ + start, buffer_ + start + 1, size_ - start - 1) 355 for (char* move = buffer_ + start, *end = buffer_ + size_ - 1; 356 move < end; 357 ++move) { 358 *move = move[1]; 359 } 360 ++discarded; 361 --count_; 362 } else if (count_ - size_ > 1) { 363 // Need to increment either |count_| or |discarded| to make progress. 364 // The latter is more efficient, as it eventually triggers fast 365 // handling of padding. But we have to ensure we don't accidentally 366 // change the overall state (i.e. switch the state-machine from 367 // discarding to non-discarding). |count_| needs to always stay 368 // bigger than |size_|. 369 --count_; 370 ++discarded; 371 } 372 } 373 374 // Output the next digit and (if necessary) compensate for the most 375 // negative integer needing special treatment. This works because, 376 // no matter the bit width of the integer, the lowest-most decimal 377 // integer always ends in 2, 4, 6, or 8. 378 if (!num && started) { 379 if (reverse_prefix > prefix) { 380 Out(*--reverse_prefix); 381 } else { 382 Out(pad); 383 } 384 } else { 385 started = true; 386 Out((upcase ? kUpCaseHexDigits : kDownCaseHexDigits)[num%base + minint]); 387 } 388 389 minint = 0; 390 num /= base; 391 392 // Add padding, if requested. 393 if (padding > 0) { 394 --padding; 395 396 // Performance optimization for when we are asked to output excessive 397 // padding, but our output buffer is limited in size. Even if we output 398 // a 64bit number in binary, we would never write more than 64 plus 399 // prefix non-padding characters. So, once this limit has been passed, 400 // any further state change can be computed arithmetically; we know that 401 // by this time, our entire final output consists of padding characters 402 // that have all already been output. 403 if (discarded > 8*sizeof(num) + prefix_length) { 404 IncrementCount(padding); 405 padding = 0; 406 } 407 } 408 } while (num || padding || (reverse_prefix > prefix)); 409 410 // Conversion to ASCII actually resulted in the digits being in reverse 411 // order. We can't easily generate them in forward order, as we can't tell 412 // the number of characters needed until we are done converting. 413 // So, now, we reverse the string (except for the possible '-' sign). 414 char* front = buffer_ + start; 415 char* back = GetInsertionPoint(); 416 while (--back > front) { 417 char ch = *back; 418 *back = *front; 419 *front++ = ch; 420 } 421 422 IncrementCount(discarded); 423 return !discarded; 424} 425 426} // anonymous namespace 427 428namespace internal { 429 430ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args, 431 const size_t max_args) { 432 // Make sure that at least one NUL byte can be written, and that the buffer 433 // never overflows kSSizeMax. Not only does that use up most or all of the 434 // address space, it also would result in a return code that cannot be 435 // represented. 436 if (static_cast<ssize_t>(sz) < 1) { 437 return -1; 438 } else if (sz > kSSizeMax) { 439 sz = kSSizeMax; 440 } 441 442 // Iterate over format string and interpret '%' arguments as they are 443 // encountered. 444 Buffer buffer(buf, sz); 445 size_t padding; 446 char pad; 447 for (unsigned int cur_arg = 0; *fmt && !buffer.OutOfAddressableSpace(); ) { 448 if (*fmt++ == '%') { 449 padding = 0; 450 pad = ' '; 451 char ch = *fmt++; 452 format_character_found: 453 switch (ch) { 454 case '0': case '1': case '2': case '3': case '4': 455 case '5': case '6': case '7': case '8': case '9': 456 // Found a width parameter. Convert to an integer value and store in 457 // "padding". If the leading digit is a zero, change the padding 458 // character from a space ' ' to a zero '0'. 459 pad = ch == '0' ? '0' : ' '; 460 for (;;) { 461 // The maximum allowed padding fills all the available address 462 // space and leaves just enough space to insert the trailing NUL. 463 const size_t max_padding = kSSizeMax - 1; 464 if (padding > max_padding/10 || 465 10*padding > max_padding - (ch - '0')) { 466 DEBUG_CHECK(padding <= max_padding/10 && 467 10*padding <= max_padding - (ch - '0')); 468 // Integer overflow detected. Skip the rest of the width until 469 // we find the format character, then do the normal error handling. 470 padding_overflow: 471 padding = max_padding; 472 while ((ch = *fmt++) >= '0' && ch <= '9') { 473 } 474 if (cur_arg < max_args) { 475 ++cur_arg; 476 } 477 goto fail_to_expand; 478 } 479 padding = 10*padding + ch - '0'; 480 if (padding > max_padding) { 481 // This doesn't happen for "sane" values of kSSizeMax. But once 482 // kSSizeMax gets smaller than about 10, our earlier range checks 483 // are incomplete. Unittests do trigger this artificial corner 484 // case. 485 DEBUG_CHECK(padding <= max_padding); 486 goto padding_overflow; 487 } 488 ch = *fmt++; 489 if (ch < '0' || ch > '9') { 490 // Reached the end of the width parameter. This is where the format 491 // character is found. 492 goto format_character_found; 493 } 494 } 495 break; 496 case 'c': { // Output an ASCII character. 497 // Check that there are arguments left to be inserted. 498 if (cur_arg >= max_args) { 499 DEBUG_CHECK(cur_arg < max_args); 500 goto fail_to_expand; 501 } 502 503 // Check that the argument has the expected type. 504 const Arg& arg = args[cur_arg++]; 505 if (arg.type != Arg::INT && arg.type != Arg::UINT) { 506 DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT); 507 goto fail_to_expand; 508 } 509 510 // Apply padding, if needed. 511 buffer.Pad(' ', padding, 1); 512 513 // Convert the argument to an ASCII character and output it. 514 char as_char = static_cast<char>(arg.integer.i); 515 if (!as_char) { 516 goto end_of_output_buffer; 517 } 518 buffer.Out(as_char); 519 break; } 520 case 'd': // Output a possibly signed decimal value. 521 case 'o': // Output an unsigned octal value. 522 case 'x': // Output an unsigned hexadecimal value. 523 case 'X': 524 case 'p': { // Output a pointer value. 525 // Check that there are arguments left to be inserted. 526 if (cur_arg >= max_args) { 527 DEBUG_CHECK(cur_arg < max_args); 528 goto fail_to_expand; 529 } 530 531 const Arg& arg = args[cur_arg++]; 532 int64_t i; 533 const char* prefix = NULL; 534 if (ch != 'p') { 535 // Check that the argument has the expected type. 536 if (arg.type != Arg::INT && arg.type != Arg::UINT) { 537 DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT); 538 goto fail_to_expand; 539 } 540 i = arg.integer.i; 541 542 if (ch != 'd') { 543 // The Arg() constructor automatically performed sign expansion on 544 // signed parameters. This is great when outputting a %d decimal 545 // number, but can result in unexpected leading 0xFF bytes when 546 // outputting a %x hexadecimal number. Mask bits, if necessary. 547 // We have to do this here, instead of in the Arg() constructor, as 548 // the Arg() constructor cannot tell whether we will output a %d 549 // or a %x. Only the latter should experience masking. 550 if (arg.integer.width < sizeof(int64_t)) { 551 i &= (1LL << (8*arg.integer.width)) - 1; 552 } 553 } 554 } else { 555 // Pointer values require an actual pointer or a string. 556 if (arg.type == Arg::POINTER) { 557 i = reinterpret_cast<uintptr_t>(arg.ptr); 558 } else if (arg.type == Arg::STRING) { 559 i = reinterpret_cast<uintptr_t>(arg.str); 560 } else if (arg.type == Arg::INT && 561 arg.integer.width == sizeof(NULL) && 562 arg.integer.i == 0) { // Allow C++'s version of NULL 563 i = 0; 564 } else { 565 DEBUG_CHECK(arg.type == Arg::POINTER || arg.type == Arg::STRING); 566 goto fail_to_expand; 567 } 568 569 // Pointers always include the "0x" prefix. 570 prefix = "0x"; 571 } 572 573 // Use IToASCII() to convert to ASCII representation. For decimal 574 // numbers, optionally print a sign. For hexadecimal numbers, 575 // distinguish between upper and lower case. %p addresses are always 576 // printed as upcase. Supports base 8, 10, and 16. Prints padding 577 // and/or prefixes, if so requested. 578 buffer.IToASCII(ch == 'd' && arg.type == Arg::INT, 579 ch != 'x', i, 580 ch == 'o' ? 8 : ch == 'd' ? 10 : 16, 581 pad, padding, prefix); 582 break; } 583 case 's': { 584 // Check that there are arguments left to be inserted. 585 if (cur_arg >= max_args) { 586 DEBUG_CHECK(cur_arg < max_args); 587 goto fail_to_expand; 588 } 589 590 // Check that the argument has the expected type. 591 const Arg& arg = args[cur_arg++]; 592 const char *s; 593 if (arg.type == Arg::STRING) { 594 s = arg.str ? arg.str : "<NULL>"; 595 } else if (arg.type == Arg::INT && arg.integer.width == sizeof(NULL) && 596 arg.integer.i == 0) { // Allow C++'s version of NULL 597 s = "<NULL>"; 598 } else { 599 DEBUG_CHECK(arg.type == Arg::STRING); 600 goto fail_to_expand; 601 } 602 603 // Apply padding, if needed. This requires us to first check the 604 // length of the string that we are outputting. 605 if (padding) { 606 size_t len = 0; 607 for (const char* src = s; *src++; ) { 608 ++len; 609 } 610 buffer.Pad(' ', padding, len); 611 } 612 613 // Printing a string involves nothing more than copying it into the 614 // output buffer and making sure we don't output more bytes than 615 // available space; Out() takes care of doing that. 616 for (const char* src = s; *src; ) { 617 buffer.Out(*src++); 618 } 619 break; } 620 case '%': 621 // Quoted percent '%' character. 622 goto copy_verbatim; 623 fail_to_expand: 624 // C++ gives us tools to do type checking -- something that snprintf() 625 // could never really do. So, whenever we see arguments that don't 626 // match up with the format string, we refuse to output them. But 627 // since we have to be extremely conservative about being async- 628 // signal-safe, we are limited in the type of error handling that we 629 // can do in production builds (in debug builds we can use 630 // DEBUG_CHECK() and hope for the best). So, all we do is pass the 631 // format string unchanged. That should eventually get the user's 632 // attention; and in the meantime, it hopefully doesn't lose too much 633 // data. 634 default: 635 // Unknown or unsupported format character. Just copy verbatim to 636 // output. 637 buffer.Out('%'); 638 DEBUG_CHECK(ch); 639 if (!ch) { 640 goto end_of_format_string; 641 } 642 buffer.Out(ch); 643 break; 644 } 645 } else { 646 copy_verbatim: 647 buffer.Out(fmt[-1]); 648 } 649 } 650 end_of_format_string: 651 end_of_output_buffer: 652 return buffer.GetCount(); 653} 654 655} // namespace internal 656 657ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt) { 658 // Make sure that at least one NUL byte can be written, and that the buffer 659 // never overflows kSSizeMax. Not only does that use up most or all of the 660 // address space, it also would result in a return code that cannot be 661 // represented. 662 if (static_cast<ssize_t>(sz) < 1) { 663 return -1; 664 } else if (sz > kSSizeMax) { 665 sz = kSSizeMax; 666 } 667 668 Buffer buffer(buf, sz); 669 670 // In the slow-path, we deal with errors by copying the contents of 671 // "fmt" unexpanded. This means, if there are no arguments passed, the 672 // SafeSPrintf() function always degenerates to a version of strncpy() that 673 // de-duplicates '%' characters. 674 const char* src = fmt; 675 for (; *src; ++src) { 676 buffer.Out(*src); 677 DEBUG_CHECK(src[0] != '%' || src[1] == '%'); 678 if (src[0] == '%' && src[1] == '%') { 679 ++src; 680 } 681 } 682 return buffer.GetCount(); 683} 684 685} // namespace strings 686} // namespace base 687