@@ -123,41 +123,48 @@ void ErrorHandler(Int_t level, const char *location, const char *fmt, std::va_li
123123 std::va_list apCopy;
124124 va_copy (apCopy, ap);
125125
126- // Figure out exactly how many bytes we need
127- int nRequired = vsnprintf (nullptr , 0 , fmt, ap) + 1 ;
126+ // Write the user string to the current buffer and, at the same time, figure out exactly how many bytes we need.
127+ int nWritten = vsnprintf (buf, bufSize, fmt, ap);
128+ int nAdditional = 0 ;
128129 if (level >= kSysError && level < kFatal ) {
129130 auto sysHandler = GetErrorSystemMsgHandlerRef ();
130131 if (sysHandler)
131- nRequired + = strlen (sysHandler ()) + 1 ; // +1 for the whitespace
132+ nAdditional = strlen (sysHandler ()) + 1 ; // +1 for the whitespace
132133 else {
133- nRequired + = snprintf (nullptr , 0 , " (errno: %d)" , errno) + 1 ;
134+ nAdditional = snprintf (nullptr , 0 , " (errno: %d)" , errno);
134135 }
135136 }
136137
138+ // nWritten and nAdditional are the number of characters, nRequired is the required
139+ // number of bytes, hence the + 1 for the null terminator.
140+ int nRequired = nWritten + nAdditional + 1 ;
137141 if (nRequired >= bufSize) {
138- // Not enough space: allocate more space on the heap to fit the string
142+ // Not enough space: allocate more space on the heap to fit the string.
139143 if (buf != smallBuf)
140144 delete[] buf;
141145
142- bufSize = std::max (bufSize * 2 , nRequired + 1 );
146+ bufSize = std::max (bufSize * 2 , nRequired);
143147 buf = bufDynStorage = new char [bufSize];
148+ // Write the user string again in the new buffer.
149+ vsnprintf (buf, bufSize, fmt, apCopy);
144150 }
151+ va_end (apCopy);
152+
153+ assert (nRequired <= bufSize);
145154
146- // Actually write the string
147- int nWrittenPre = vsnprintf (buf, bufSize, fmt, apCopy);
155+ // if necessary, write the additional string.
156+ // NOTE: this will overwrite the null byte written by the previous vsnprintf, extending the string.
148157 int nWrittenPost = 0 ;
149- if (level >= kSysError && level < kFatal ) {
158+ if (nAdditional > 0 ) {
150159 auto sysHandler = GetErrorSystemMsgHandlerRef ();
151160 if (sysHandler) {
152- // NOTE: overwriting the null byte written by the previous vsnprintf
153- nWrittenPost = snprintf (buf + nWrittenPre, bufSize - nWrittenPre, " %s" , sysHandler ());
161+ nWrittenPost = snprintf (buf + nWritten, bufSize - nWritten, " %s" , sysHandler ());
154162 } else {
155- // NOTE: overwriting the null byte written by the previous vsnprintf
156- nWrittenPost = snprintf (buf + nWrittenPre, bufSize - nWrittenPre, " (errno: %d)" , errno);
163+ nWrittenPost = snprintf (buf + nWritten, bufSize - nWritten, " (errno: %d)" , errno);
157164 }
158165 }
159- assert (nWrittenPre + nWrittenPost + 1 <= nRequired );
160- va_end (apCopy );
166+ assert (nWrittenPost == nAdditional );
167+ assert (nWritten + nWrittenPost + 1 <= nRequired );
161168
162169 if (level != kFatal )
163170 gErrorHandler (level, level >= gErrorAbortLevel , location, buf);
0 commit comments