17db96d56Sopenharmony_ci#include "Python.h" 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci/* snprintf() and vsnprintf() wrappers. 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci If the platform has vsnprintf, we use it, else we 67db96d56Sopenharmony_ci emulate it in a half-hearted way. Even if the platform has it, we wrap 77db96d56Sopenharmony_ci it because platforms differ in what vsnprintf does in case the buffer 87db96d56Sopenharmony_ci is too small: C99 behavior is to return the number of characters that 97db96d56Sopenharmony_ci would have been written had the buffer not been too small, and to set 107db96d56Sopenharmony_ci the last byte of the buffer to \0. At least MS _vsnprintf returns a 117db96d56Sopenharmony_ci negative value instead, and fills the entire buffer with non-\0 data. 127db96d56Sopenharmony_ci Unlike C99, our wrappers do not support passing a null buffer. 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ci The wrappers ensure that str[size-1] is always \0 upon return. 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci PyOS_snprintf and PyOS_vsnprintf never write more than size bytes 177db96d56Sopenharmony_ci (including the trailing '\0') into str. 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci Return value (rv): 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci When 0 <= rv < size, the output conversion was unexceptional, and 227db96d56Sopenharmony_ci rv characters were written to str (excluding a trailing \0 byte at 237db96d56Sopenharmony_ci str[rv]). 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci When rv >= size, output conversion was truncated, and a buffer of 267db96d56Sopenharmony_ci size rv+1 would have been needed to avoid truncation. str[size-1] 277db96d56Sopenharmony_ci is \0 in this case. 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci When rv < 0, "something bad happened". str[size-1] is \0 in this 307db96d56Sopenharmony_ci case too, but the rest of str is unreliable. It could be that 317db96d56Sopenharmony_ci an error in format codes was detected by libc, or on platforms 327db96d56Sopenharmony_ci with a non-C99 vsnprintf simply that the buffer wasn't big enough 337db96d56Sopenharmony_ci to avoid truncation, or on platforms without any vsnprintf that 347db96d56Sopenharmony_ci PyMem_Malloc couldn't obtain space for a temp buffer. 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci CAUTION: Unlike C99, str != NULL and size > 0 are required. 377db96d56Sopenharmony_ci Also, size must be smaller than INT_MAX. 387db96d56Sopenharmony_ci*/ 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ciint 417db96d56Sopenharmony_ciPyOS_snprintf(char *str, size_t size, const char *format, ...) 427db96d56Sopenharmony_ci{ 437db96d56Sopenharmony_ci int rc; 447db96d56Sopenharmony_ci va_list va; 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_ci va_start(va, format); 477db96d56Sopenharmony_ci rc = PyOS_vsnprintf(str, size, format, va); 487db96d56Sopenharmony_ci va_end(va); 497db96d56Sopenharmony_ci return rc; 507db96d56Sopenharmony_ci} 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ciint 537db96d56Sopenharmony_ciPyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) 547db96d56Sopenharmony_ci{ 557db96d56Sopenharmony_ci assert(str != NULL); 567db96d56Sopenharmony_ci assert(size > 0); 577db96d56Sopenharmony_ci assert(size <= (INT_MAX - 1)); 587db96d56Sopenharmony_ci assert(format != NULL); 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci int len; /* # bytes written, excluding \0 */ 617db96d56Sopenharmony_ci /* We take a size_t as input but return an int. Sanity check 627db96d56Sopenharmony_ci * our input so that it won't cause an overflow in the 637db96d56Sopenharmony_ci * vsnprintf return value. */ 647db96d56Sopenharmony_ci if (size > INT_MAX - 1) { 657db96d56Sopenharmony_ci len = -666; 667db96d56Sopenharmony_ci goto Done; 677db96d56Sopenharmony_ci } 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci#if defined(_MSC_VER) 707db96d56Sopenharmony_ci len = _vsnprintf(str, size, format, va); 717db96d56Sopenharmony_ci#else 727db96d56Sopenharmony_ci len = vsnprintf(str, size, format, va); 737db96d56Sopenharmony_ci#endif 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ciDone: 767db96d56Sopenharmony_ci if (size > 0) { 777db96d56Sopenharmony_ci str[size-1] = '\0'; 787db96d56Sopenharmony_ci } 797db96d56Sopenharmony_ci return len; 807db96d56Sopenharmony_ci} 81