Skip to content

Print.printf() always runs vsnprintf twice  #3181

Closed
@knifter

Description

@knifter

It seems to me that Print.printf(fmt, ...) is allocating a local buffer but never actually uses it, always running vsnprintf() twice. A buffer of size 64 is allocated but then vsnprintf is called with (NULL, 0, ...) parameters just to calculate the length. Then it always allocates a new buffer to vsnprintf into. I've modified the code in such a way that loc_buf[64] is used at first and if it proofs insufficient, only then allocate another. I think this was the original idea.

Also: vsnprintf() returns int, and negative int for an error. I guess this may wreck havoc in various ways when that gets assigned to size_t (uint) and becomes some (large) positive number.

Have a look at this diff for the problem and the fix:

diff --git a/cores/esp32/Print.cpp b/cores/esp32/Print.cpp
index 8c29534..57d725f 100644
--- a/cores/esp32/Print.cpp
+++ b/cores/esp32/Print.cpp
@@ -52,15 +52,19 @@ size_t Print::printf(const char *format, ...)
     va_list copy;
     va_start(arg, format);
     va_copy(copy, arg);
-    size_t len = vsnprintf(NULL, 0, format, copy);
+    int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
     va_end(copy);
+    if(len < 0) {
+        va_end(arg);
+        return 0;
+    };
     if(len >= sizeof(loc_buf)){
         temp = new char[len+1];
         if(temp == NULL) {
             return 0;
         }
+        len = vsnprintf(temp, len+1, format, arg);
     }
-    len = vsnprintf(temp, len+1, format, arg);
     write((uint8_t*)temp, len);
     va_end(arg);
     if(len >= sizeof(loc_buf)){

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: StaleIssue is stale stage (outdated/stuck)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions