summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-05-23 13:19:12 -0400
committerAdam <Adam@anope.org>2013-05-23 13:19:12 -0400
commitda69771af628c6d16b5840f3d642ef70fcbe2170 (patch)
treec9a7849e6f20577a32b0e7143d099316a13692c6
parent27f046550c96714bc78a5e1499431da17c24408a (diff)
Some systems with whacky va_list implementations do undefined stuff when vsnprintf is called multiple times with the same list, so have InspIRCd::Format va_copy the list before each call
-rw-r--r--src/helperfuncs.cpp18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp
index cc760c535..e86c0bc70 100644
--- a/src/helperfuncs.cpp
+++ b/src/helperfuncs.cpp
@@ -401,10 +401,22 @@ unsigned long InspIRCd::Duration(const std::string &str)
const char* InspIRCd::Format(va_list &vaList, const char* formatString)
{
static std::vector<char> formatBuffer(1024);
- int vsnret = 0;
- while ((vsnret = vsnprintf(&formatBuffer[0], formatBuffer.size(), formatString, vaList)) < 0 || static_cast<unsigned int>(vsnret) >= formatBuffer.size())
+
+ while (true)
+ {
+ va_list dst;
+ va_copy(dst, vaList);
+
+ int vsnret = vsnprintf(&formatBuffer[0], formatBuffer.size(), formatString, dst);
+ if (vsnret > 0 && static_cast<unsigned>(vsnret) < formatBuffer.size())
+ {
+ return &formatBuffer[0];
+ }
+
formatBuffer.resize(formatBuffer.size() * 2);
- return &formatBuffer[0];
+ }
+
+ throw CoreException();
}
const char* InspIRCd::Format(const char* formatString, ...)