summaryrefslogtreecommitdiff
path: root/include/llvm/Support/Format.h
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-08-23 20:31:39 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-08-23 20:31:39 +0000
commit9441cfe4880018a85af9710ad405d4f2e522acc2 (patch)
treece52791943346ccf557a8aa28979b3f157d58f4e /include/llvm/Support/Format.h
parenta235d13217ff14621a88f3ea96a8a3b980c56d02 (diff)
downloadllvm-9441cfe4880018a85af9710ad405d4f2e522acc2.tar.gz
llvm-9441cfe4880018a85af9710ad405d4f2e522acc2.tar.bz2
llvm-9441cfe4880018a85af9710ad405d4f2e522acc2.tar.xz
Fix off-by-one in llvm::Format::print.
- This also shortens the Format.h implementation, and uses the print buffer fully (it was wasting a character). - This manifested as llvm-test failures, because one side effect was that raw_ostream would write garbage '\x00' values into the output stream if it happened that the string was at the end of the buffer. This meant that grep would report 'Binary file matches', which meant the silly pattern matching llvm-test eventually does would fail. Cute. :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79862 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Support/Format.h')
-rw-r--r--include/llvm/Support/Format.h61
1 files changed, 27 insertions, 34 deletions
diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h
index 2ab097faf5..df03f66ddc 100644
--- a/include/llvm/Support/Format.h
+++ b/include/llvm/Support/Format.h
@@ -36,6 +36,10 @@ class format_object_base {
protected:
const char *Fmt;
virtual void home(); // Out of line virtual method.
+
+ /// snprint - Call snprintf() for this object, on the given buffer and size.
+ virtual int snprint(char *Buffer, unsigned BufferSize) const = 0;
+
public:
format_object_base(const char *fmt) : Fmt(fmt) {}
virtual ~format_object_base() {}
@@ -43,7 +47,23 @@ public:
/// print - Format the object into the specified buffer. On success, this
/// returns the length of the formatted string. If the buffer is too small,
/// this returns a length to retry with, which will be larger than BufferSize.
- virtual unsigned print(char *Buffer, unsigned BufferSize) const = 0;
+ unsigned print(char *Buffer, unsigned BufferSize) const {
+ assert(BufferSize && "Invalid buffer size!");
+
+ // Print the string, leaving room for the terminating null.
+ int N = snprint(Buffer, BufferSize);
+
+ // VC++ and old GlibC return negative on overflow, just double the size.
+ if (N < 0)
+ return BufferSize*2;
+
+ // Other impls yield number of bytes needed, not including the final '\0'.
+ if (unsigned(N) >= BufferSize)
+ return N+1;
+
+ // Otherwise N is the length of output (not including the final '\0').
+ return N;
+ }
};
/// format_object1 - This is a templated helper class used by the format
@@ -58,17 +78,8 @@ public:
: format_object_base(fmt), Val(val) {
}
- /// print - Format the object into the specified buffer. On success, this
- /// returns the length of the formatted string. If the buffer is too small,
- /// this returns a length to retry with, which will be larger than BufferSize.
- virtual unsigned print(char *Buffer, unsigned BufferSize) const {
- int N = snprintf(Buffer, BufferSize-1, Fmt, Val);
- if (N < 0) // VC++ and old GlibC return negative on overflow.
- return BufferSize*2;
- if (unsigned(N) >= BufferSize-1)// Other impls yield number of bytes needed.
- return N+1;
- // If N is positive and <= BufferSize-1, then the string fit, yay.
- return N;
+ virtual int snprint(char *Buffer, unsigned BufferSize) const {
+ return snprintf(Buffer, BufferSize, Fmt, Val);
}
};
@@ -85,17 +96,8 @@ public:
: format_object_base(fmt), Val1(val1), Val2(val2) {
}
- /// print - Format the object into the specified buffer. On success, this
- /// returns the length of the formatted string. If the buffer is too small,
- /// this returns a length to retry with, which will be larger than BufferSize.
- virtual unsigned print(char *Buffer, unsigned BufferSize) const {
- int N = snprintf(Buffer, BufferSize-1, Fmt, Val1, Val2);
- if (N < 0) // VC++ and old GlibC return negative on overflow.
- return BufferSize*2;
- if (unsigned(N) >= BufferSize-1)// Other impls yield number of bytes needed.
- return N+1;
- // If N is positive and <= BufferSize-1, then the string fit, yay.
- return N;
+ virtual int snprint(char *Buffer, unsigned BufferSize) const {
+ return snprintf(Buffer, BufferSize, Fmt, Val1, Val2);
}
};
@@ -113,17 +115,8 @@ public:
: format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) {
}
- /// print - Format the object into the specified buffer. On success, this
- /// returns the length of the formatted string. If the buffer is too small,
- /// this returns a length to retry with, which will be larger than BufferSize.
- virtual unsigned print(char *Buffer, unsigned BufferSize) const {
- int N = snprintf(Buffer, BufferSize-1, Fmt, Val1, Val2, Val3);
- if (N < 0) // VC++ and old GlibC return negative on overflow.
- return BufferSize*2;
- if (unsigned(N) >= BufferSize-1)// Other impls yield number of bytes needed.
- return N+1;
- // If N is positive and <= BufferSize-1, then the string fit, yay.
- return N;
+ virtual int snprint(char *Buffer, unsigned BufferSize) const {
+ return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3);
}
};