Bug 1334279 - mark vsprintf-likes with MOZ_FORMAT_PRINTF; r=froydnj
authorTom Tromey <tom@tromey.com>
Thu, 04 May 2017 12:10:19 -0600
changeset 407547 8ce8c07e3e2928ef9d27c53225a6bb6a121799ba
parent 407546 709528f44f789e33698e8793413643ca584afbef
child 407548 7fd5149580359a37db19d1345f722d25e18de9fa
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1334279
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1334279 - mark vsprintf-likes with MOZ_FORMAT_PRINTF; r=froydnj This annotates vsprintf-like functions with MOZ_FORMAT_PRINTF. This may provide some minimal checking of such calls (the GCC docs say that it checks for the string for "consistency"); but in any case shouldn't hurt. MozReview-Commit-ID: HgnAK1LiorE
dom/canvas/WebGLContext.h
js/src/jit/JitSpewer.h
js/src/jit/MIRGenerator.h
js/src/jit/arm/Assembler-arm.h
js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h
js/src/jscntxt.h
js/src/jsprf.h
js/src/vm/Printer.h
js/src/wasm/AsmJS.cpp
mfbt/Attributes.h
mfbt/Sprintf.h
mozglue/misc/Printf.h
xpcom/base/Logging.cpp
xpcom/base/Logging.h
xpcom/base/nsDebug.h
xpcom/string/nsTSubstring.h
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -2049,17 +2049,17 @@ protected:
     // because WebGLContext objects only go away during GC, which shouldn't happen too frequently.
     // If in the future GC becomes much more frequent, we may have to revisit then (maybe use a timer).
     ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper;
 #endif
 
 public:
     // console logging helpers
     void GenerateWarning(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
-    void GenerateWarning(const char* fmt, va_list ap);
+    void GenerateWarning(const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(2, 0);
 
     void GeneratePerfWarning(const char* fmt, ...) const MOZ_FORMAT_PRINTF(2, 3);
 
 public:
     UniquePtr<webgl::FormatUsageAuthority> mFormatUsage;
 
     virtual UniquePtr<webgl::FormatUsageAuthority>
     CreateFormatUsage(gl::GLContext* gl) const = 0;
--- a/js/src/jit/JitSpewer.h
+++ b/js/src/jit/JitSpewer.h
@@ -178,19 +178,19 @@ class JitSpewIndent
 };
 
 void JitSpew(JitSpewChannel channel, const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
 void JitSpewStart(JitSpewChannel channel, const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
 void JitSpewCont(JitSpewChannel channel, const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
 void JitSpewFin(JitSpewChannel channel);
 void JitSpewHeader(JitSpewChannel channel);
 bool JitSpewEnabled(JitSpewChannel channel);
-void JitSpewVA(JitSpewChannel channel, const char* fmt, va_list ap);
-void JitSpewStartVA(JitSpewChannel channel, const char* fmt, va_list ap);
-void JitSpewContVA(JitSpewChannel channel, const char* fmt, va_list ap);
+void JitSpewVA(JitSpewChannel channel, const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(2, 0);
+void JitSpewStartVA(JitSpewChannel channel, const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(2, 0);
+void JitSpewContVA(JitSpewChannel channel, const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(2, 0);
 void JitSpewDef(JitSpewChannel channel, const char* str, MDefinition* def);
 
 void EnableChannel(JitSpewChannel channel);
 void DisableChannel(JitSpewChannel channel);
 void EnableIonDebugSyncLogging();
 void EnableIonDebugAsyncLogging();
 
 #else
@@ -248,17 +248,18 @@ static inline void JitSpewCheckArguments
 
 static inline void JitSpewFin(JitSpewChannel channel)
 { }
 
 static inline void JitSpewHeader(JitSpewChannel channel)
 { }
 static inline bool JitSpewEnabled(JitSpewChannel channel)
 { return false; }
-static inline void JitSpewVA(JitSpewChannel channel, const char* fmt, va_list ap)
+static inline MOZ_FORMAT_PRINTF(2, 0)
+void JitSpewVA(JitSpewChannel channel, const char* fmt, va_list ap)
 { }
 static inline void JitSpewDef(JitSpewChannel channel, const char* str, MDefinition* def)
 { }
 
 static inline void EnableChannel(JitSpewChannel)
 { }
 static inline void DisableChannel(JitSpewChannel)
 { }
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -72,17 +72,17 @@ class MIRGenerator
 
     // Set an error state and prints a message. Returns false so errors can be
     // propagated up.
     mozilla::GenericErrorResult<AbortReason> abort(AbortReason r);
     mozilla::GenericErrorResult<AbortReason>
     abort(AbortReason r, const char* message, ...) MOZ_FORMAT_PRINTF(3, 4);
 
     mozilla::GenericErrorResult<AbortReason>
-    abortFmt(AbortReason r, const char* message, va_list ap);
+    abortFmt(AbortReason r, const char* message, va_list ap) MOZ_FORMAT_PRINTF(3, 0);
 
     // Collect the evaluation result of phases after IonBuilder, such that
     // off-thread compilation can report what error got encountered.
     void setOffThreadStatus(AbortReasonOr<Ok> result) {
         MOZ_ASSERT(offThreadStatus_.isOk());
         offThreadStatus_ = result;
     }
     AbortReasonOr<Ok> getOffThreadStatus() const {
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -1312,17 +1312,17 @@ class Assembler : public AssemblerShared
     uint32_t spewNext_;
     Sprinter* printer_;
 
     bool spewDisabled();
     uint32_t spewResolve(Label* l);
     uint32_t spewProbe(Label* l);
     uint32_t spewDefine(Label* l);
     void spew(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
-    void spew(const char* fmt, va_list args);
+    void spew(const char* fmt, va_list args) MOZ_FORMAT_PRINTF(2, 0);
 #endif
 
   public:
     // For the alignment fill use NOP: 0x0320f000 or (Always | InstNOP::NopInst).
     // For the nopFill use a branch to the next instruction: 0xeaffffff.
     Assembler()
       : m_buffer(1, 1, 8, GetPoolMaxOffset(), 8, 0xe320f000, 0xeaffffff, GetNopFill()),
 #ifdef JS_DISASM_ARM
--- a/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h
+++ b/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h
@@ -218,16 +218,16 @@ namespace jit {
                 va_start(va, fmt);
                 spew(fmt, va);
                 va_end(va);
             }
 #endif
         }
 
 #ifdef JS_JITSPEW
-        MOZ_COLD void spew(const char* fmt, va_list va);
+        MOZ_COLD void spew(const char* fmt, va_list va) MOZ_FORMAT_PRINTF(2, 0);
 #endif
     };
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x86_shared_AssemblerBuffer_x86_shared_h */
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1019,17 +1019,17 @@ enum ErrorArgumentsType {
  * Defined in SelfHosting.cpp.
  */
 JSFunction*
 SelfHostedFunction(JSContext* cx, HandlePropertyName propName);
 
 #ifdef va_start
 extern bool
 ReportErrorVA(JSContext* cx, unsigned flags, const char* format,
-              ErrorArgumentsType argumentsType, va_list ap);
+              ErrorArgumentsType argumentsType, va_list ap) MOZ_FORMAT_PRINTF(3, 0);
 
 extern bool
 ReportErrorNumberVA(JSContext* cx, unsigned flags, JSErrorCallback callback,
                     void* userRef, const unsigned errorNumber,
                     ErrorArgumentsType argumentsType, va_list ap);
 
 extern bool
 ReportErrorNumberUCArray(JSContext* cx, unsigned flags, JSErrorCallback callback,
--- a/js/src/jsprf.h
+++ b/js/src/jsprf.h
@@ -21,13 +21,15 @@ extern JS_PUBLIC_API(JS::UniqueChars) JS
     MOZ_FORMAT_PRINTF(1, 2);
 
 extern JS_PUBLIC_API(void) JS_smprintf_free(char* mem);
 
 extern JS_PUBLIC_API(JS::UniqueChars) JS_sprintf_append(JS::UniqueChars&& last,
                                                         const char* fmt, ...)
      MOZ_FORMAT_PRINTF(2, 3);
 
-extern JS_PUBLIC_API(JS::UniqueChars) JS_vsmprintf(const char* fmt, va_list ap);
+extern JS_PUBLIC_API(JS::UniqueChars) JS_vsmprintf(const char* fmt, va_list ap)
+    MOZ_FORMAT_PRINTF(1, 0);
 extern JS_PUBLIC_API(JS::UniqueChars) JS_vsprintf_append(JS::UniqueChars&& last,
-                                                         const char* fmt, va_list ap);
+                                                         const char* fmt, va_list ap)
+    MOZ_FORMAT_PRINTF(2, 0);
 
 #endif /* jsprf_h */
--- a/js/src/vm/Printer.h
+++ b/js/src/vm/Printer.h
@@ -40,17 +40,17 @@ class GenericPrinter
     virtual bool put(const char* s, size_t len) = 0;
 
     inline bool put(const char* s) {
         return put(s, strlen(s));
     }
 
     // Prints a formatted string into the buffer.
     bool printf(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
-    bool vprintf(const char* fmt, va_list ap);
+    bool vprintf(const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(2, 0);
 
     // Report that a string operation failed to get the memory it requested. The
     // first call to this function calls JS_ReportOutOfMemory, and sets this
     // Sprinter's outOfMemory flag; subsequent calls do nothing.
     virtual void reportOutOfMemory();
 
     // Return true if this Sprinter ran out of memory.
     virtual bool hadOutOfMemory() const;
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -2263,17 +2263,17 @@ class MOZ_STACK_CLASS ModuleValidator
     bool failCurrentOffset(const char* str) {
         return failOffset(tokenStream().currentToken().pos.begin, str);
     }
 
     bool fail(ParseNode* pn, const char* str) {
         return failOffset(pn->pn_pos.begin, str);
     }
 
-    bool failfVAOffset(uint32_t offset, const char* fmt, va_list ap) {
+    bool failfVAOffset(uint32_t offset, const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(3, 0) {
         MOZ_ASSERT(!hasAlreadyFailed());
         MOZ_ASSERT(errorOffset_ == UINT32_MAX);
         MOZ_ASSERT(fmt);
         errorOffset_ = offset;
         errorString_ = JS_vsmprintf(fmt, ap);
         return false;
     }
 
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -622,16 +622,19 @@
  * So, for a simple case like:
  *   void print_something (int whatever, const char *fmt, ...);
  * The corresponding annotation would be
  *   MOZ_FORMAT_PRINTF(2, 3)
  * However, if "print_something" were a non-static member function,
  * then the annotation would be:
  *   MOZ_FORMAT_PRINTF(3, 4)
  *
+ * The second argument should be 0 for vprintf-like functions; that
+ * is, those taking a va_list argument.
+ *
  * Note that the checking is limited to standards-conforming
  * printf-likes, and in particular this should not be used for
  * PR_snprintf and friends, which are "printf-like" but which assign
  * different meanings to the various formats.
  *
  * MinGW requires special handling due to different format specifiers
  * on different platforms. The macro __MINGW_PRINTF_FORMAT maps to
  * either gnu_printf or ms_printf depending on where we are compiling
--- a/mfbt/Sprintf.h
+++ b/mfbt/Sprintf.h
@@ -13,16 +13,17 @@
 #include <stdarg.h>
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 
 #ifdef __cplusplus
 
 template <size_t N>
+MOZ_FORMAT_PRINTF(2, 0)
 int VsprintfLiteral(char (&buffer)[N], const char* format, va_list args)
 {
     MOZ_ASSERT(format != buffer);
     int result = vsnprintf(buffer, N, format, args);
     buffer[N - 1] = '\0';
     return result;
 }
 
--- a/mozglue/misc/Printf.h
+++ b/mozglue/misc/Printf.h
@@ -68,17 +68,17 @@ namespace mozilla {
  */
 class PrintfTarget
 {
 public:
     /* The Printf-like interface.  */
     bool MFBT_API print(const char* format, ...) MOZ_FORMAT_PRINTF(2, 3);
 
     /* The Vprintf-like interface.  */
-    bool MFBT_API vprint(const char* format, va_list);
+    bool MFBT_API vprint(const char* format, va_list) MOZ_FORMAT_PRINTF(2, 0);
 
 protected:
     MFBT_API PrintfTarget();
     virtual ~PrintfTarget() { }
 
     /* Subclasses override this.  It is called when more output is
        available.  It may be called with len==0.  This should return
        true on success, or false on failure.  */
@@ -135,17 +135,17 @@ class MOZ_STACK_CLASS SprintfState final
         , mCur(base ? base + mMaxlen : 0)
     {
     }
 
     ~SprintfState() {
         this->free_(mBase);
     }
 
-    bool vprint(const char* format, va_list ap_list) {
+    bool vprint(const char* format, va_list ap_list) MOZ_FORMAT_PRINTF(2, 0) {
         // The "" here has a single \0 character, which is what we're
         // trying to append.
         return mozilla::PrintfTarget::vprint(format, ap_list) && append("", 1);
     }
 
     SmprintfPolicyPointer<AllocPolicy> release() {
         SmprintfPolicyPointer<AllocPolicy> result(mBase);
         mBase = nullptr;
@@ -229,25 +229,27 @@ SmprintfPolicyPointer<AllocPolicy> Smpri
     }
     return ss.release();
 }
 
 /*
 ** va_list forms of the above.
 */
 template<typename AllocPolicy = mozilla::MallocAllocPolicy>
+MOZ_FORMAT_PRINTF(1, 0)
 SmprintfPolicyPointer<AllocPolicy> Vsmprintf(const char* fmt, va_list ap)
 {
     SprintfState<AllocPolicy> ss(nullptr);
     if (!ss.vprint(fmt, ap))
         return nullptr;
     return ss.release();
 }
 
 template<typename AllocPolicy = mozilla::MallocAllocPolicy>
+MOZ_FORMAT_PRINTF(2, 0)
 SmprintfPolicyPointer<AllocPolicy> VsmprintfAppend(SmprintfPolicyPointer<AllocPolicy>&& last,
                                                    const char* fmt, va_list ap)
 {
     SprintfState<AllocPolicy> ss(last.release());
     if (!ss.vprint(fmt, ap))
         return nullptr;
     return ss.release();
 }
--- a/xpcom/base/Logging.cpp
+++ b/xpcom/base/Logging.cpp
@@ -341,16 +341,17 @@ public:
       module = new LogModule(aName, LogLevel::Disabled);
       mModules.Put(aName, module);
     }
 
     return module;
   }
 
   void Print(const char* aName, LogLevel aLevel, const char* aFmt, va_list aArgs)
+    MOZ_FORMAT_PRINTF(4, 0)
   {
     const size_t kBuffSize = 1024;
     char buff[kBuffSize];
 
     char* buffToWrite = buff;
     SmprintfPointer allocatedBuff;
 
     va_list argsCopy;
--- a/xpcom/base/Logging.h
+++ b/xpcom/base/Logging.h
@@ -114,17 +114,17 @@ public:
   /**
    * Sets the log module's level.
    */
   void SetLevel(LogLevel level) { mLevel = level; }
 
   /**
    * Print a log message for this module.
    */
-  void Printv(LogLevel aLevel, const char* aFmt, va_list aArgs) const;
+  void Printv(LogLevel aLevel, const char* aFmt, va_list aArgs) const MOZ_FORMAT_PRINTF(3, 0);
 
   /**
    * Retrieves the module name.
    */
   const char* Name() const { return mName; }
 
 private:
   friend class LogModuleManager;
--- a/xpcom/base/nsDebug.h
+++ b/xpcom/base/nsDebug.h
@@ -388,17 +388,17 @@ extern "C" {
  *  - on Windows, if a debugger is present, it calls OutputDebugString
  *    in *addition* to writing to stderr
  */
 void printf_stderr(const char* aFmt, ...) MOZ_FORMAT_PRINTF(1, 2);
 
 /**
  * Same as printf_stderr, but taking va_list instead of varargs
  */
-void vprintf_stderr(const char* aFmt, va_list aArgs);
+void vprintf_stderr(const char* aFmt, va_list aArgs) MOZ_FORMAT_PRINTF(1, 0);
 
 /**
  * fprintf_stderr is like fprintf, except that if its file argument
  * is stderr, it invokes printf_stderr instead.
  *
  * This is useful for general debugging code that logs information to a
  * file, but that you would like to be useful on Android and Firefox OS.
  * If you use fprintf_stderr instead of fprintf in such debugging code,
--- a/xpcom/string/nsTSubstring.h
+++ b/xpcom/string/nsTSubstring.h
@@ -687,17 +687,17 @@ public:
 
   /**
    * Append a formatted string to the current string. Uses the
    * standard printf format codes.  This uses NSPR formatting, which will be
    * locale-aware for floating-point values.  You probably don't want to use
    * this with floating-point values as a result.
    */
   void AppendPrintf(const char* aFormat, ...) MOZ_FORMAT_PRINTF(2, 3);
-  void AppendPrintf(const char* aFormat, va_list aAp);
+  void AppendPrintf(const char* aFormat, va_list aAp) MOZ_FORMAT_PRINTF(2, 0);
   void AppendInt(int32_t aInteger)
   {
     AppendPrintf("%" PRId32, aInteger);
   }
   void AppendInt(int32_t aInteger, int aRadix)
   {
     if (aRadix == 10) {
       AppendPrintf("%" PRId32, aInteger);