+---
+* [Bug 3556] ntp_loopfilter.c snprintf compilation warnings <perlinger@ntp.org>
+ - provide better function for incremental string formatting
+
---
(4.2.8p12) 2018/08/14 Released by Harlan Stenn <stenn@ntp.org>
extern void errno_to_str(int, char *, size_t);
#endif
+extern int xvsbprintf(char**, char* const, char const*, va_list) NTP_PRINTF(3, 0);
+extern int xsbprintf(char**, char* const, char const*, ...) NTP_PRINTF(3, 4);
+
/*
* When building without OpenSSL, use a few macros of theirs to
* minimize source differences in NTP.
vint64ops.c \
work_fork.c \
work_thread.c \
+ xsbprintf.c \
ymd2yd.c \
$(libisc_SRCS) \
$(NULL)
--- /dev/null
+/*
+ * xsbprintf.c - string buffer formatting helpers
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ */
+
+#include <config.h>
+#include <sys/types.h>
+
+#include "ntp_stdlib.h"
+
+/* eXtended Varlist String Buffer printf
+ *
+ * Formats via 'vsnprintf' into a string buffer, with some semantic
+ * specialties:
+ *
+ * - The start of the buffer pointer is updated according to the number
+ * of characters written.
+ * - If the buffer is insufficient to format the number of charactes,
+ * the partial result will be be discarded, and zero is returned to
+ * indicate nothing was written to the buffer.
+ * - On successful formatting, the return code is the return value of
+ * the inner call to 'vsnprintf()'.
+ * - If there is any error, the state of the buffer will not be
+ * changed. (Bytes in the buffer might be smashed, but the buffer
+ * position does not change, and the NUL marker stays in place at the
+ * current buffer position.)
+ */
+int
+xvsbprintf(
+ char **ppbuf, /* pointer to buffer pointer (I/O) */
+ char * const pend, /* buffer end (I) */
+ char const *pfmt, /* printf-like format string */
+ va_list va /* formatting args for above */
+ )
+{
+ char *pbuf = (ppbuf) ? *ppbuf : NULL;
+ int rc = -1;
+ if (pbuf) {
+ size_t ilen = (size_t)(pend - pbuf);
+ if (ilen) {
+ *pbuf = '\0';
+ rc = vsnprintf(pbuf, ilen, pfmt, va);
+ if (rc > 0) {
+ if ((size_t)rc >= ilen)
+ rc = 0;
+ pbuf += rc;
+ }
+ *pbuf = '\0'; /* fear of bad vsnprintf */
+ }
+ *ppbuf = pbuf;
+ } else {
+ errno = EINVAL;
+ }
+ return rc;
+}
+
+/* variadic wrapper around the buufer string formatter */
+int
+xsbprintf(
+ char **ppbuf, /* pointer to buffer pointer (I/O) */
+ char * const pend, /* buffer end (I) */
+ char const *pfmt, /* printf-like format string */
+ ... /* formatting args for above */
+ )
+{
+ va_list va;
+ int rc;
+
+ va_start(va, pfmt);
+ rc = xvsbprintf(ppbuf, pend, pfmt, va);
+ va_end(va);
+ return rc;
+}
+
+/* that's all folks! */
)
{
char des[1024] = ""; /* Decoded Error Status */
+ char *dbp, *ebp;
+ dbp = des;
+ ebp = dbp + sizeof(des);
+
switch (ret) {
case -1:
switch (saved_errno) {
/* error (see status word) */
if (ptimex->status & STA_UNSYNC)
- snprintf(des, sizeof(des), "%s%sClock Unsynchronized",
- des, (*des) ? "; " : "");
+ xsbprintf(&dbp, ebp, "%sClock Unsynchronized",
+ (*des) ? "; " : "");
if (ptimex->status & STA_CLOCKERR)
- snprintf(des, sizeof(des), "%s%sClock Error",
- des, (*des) ? "; " : "");
+ xsbprintf(&dbp, ebp, "%sClock Error",
+ (*des) ? "; " : "");
if (!(ptimex->status & STA_PPSSIGNAL)
&& ptimex->status & STA_PPSFREQ)
- snprintf(des, sizeof(des), "%s%sPPS Frequency Sync wanted but no PPS",
- des, (*des) ? "; " : "");
+ xsbprintf(&dbp, ebp, "%sPPS Frequency Sync wanted but no PPS",
+ (*des) ? "; " : "");
if (!(ptimex->status & STA_PPSSIGNAL)
&& ptimex->status & STA_PPSTIME)
- snprintf(des, sizeof(des), "%s%sPPS Time Sync wanted but no PPS signal",
- des, (*des) ? "; " : "");
+ xsbprintf(&dbp, ebp, "%sPPS Time Sync wanted but no PPS signal",
+ (*des) ? "; " : "");
if ( ptimex->status & STA_PPSTIME
&& ptimex->status & STA_PPSJITTER)
- snprintf(des, sizeof(des), "%s%sPPS Time Sync wanted but PPS Jitter exceeded",
- des, (*des) ? "; " : "");
+ xsbprintf(&dbp, ebp, "%sPPS Time Sync wanted but PPS Jitter exceeded",
+ (*des) ? "; " : "");
if ( ptimex->status & STA_PPSFREQ
&& ptimex->status & STA_PPSWANDER)
- snprintf(des, sizeof(des), "%s%sPPS Frequency Sync wanted but PPS Wander exceeded",
- des, (*des) ? "; " : "");
+ xsbprintf(&dbp, ebp, "%sPPS Frequency Sync wanted but PPS Wander exceeded",
+ (*des) ? "; " : "");
if ( ptimex->status & STA_PPSFREQ
&& ptimex->status & STA_PPSERROR)
- snprintf(des, sizeof(des), "%s%sPPS Frequency Sync wanted but Calibration error detected",
- des, (*des) ? "; " : "");
+ xsbprintf(&dbp, ebp, "%sPPS Frequency Sync wanted but Calibration error detected",
+ (*des) ? "; " : "");
if (pps_call && !(ptimex->status & STA_PPSSIGNAL))
report_event(EVNT_KERN, NULL,
RelativePath="..\..\..\libntp\work_thread.c"
>
</File>
+ <File
+ RelativePath="..\..\..\libntp\xsbprintf.c"
+ >
+ </File>
<File
RelativePath="..\..\..\libntp\ymd2yd.c"
>
RelativePath="..\..\..\..\libntp\work_thread.c"
>
</File>
+ <File
+ RelativePath="..\..\..\..\libntp\xsbprintf.c"
+ >
+ </File>
<File
RelativePath="..\..\..\..\libntp\ymd2yd.c"
>
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugXP|Win32">
<ClCompile Include="..\..\..\..\libntp\vint64ops.c" />
<ClCompile Include="..\..\..\..\libntp\work_fork.c" />
<ClCompile Include="..\..\..\..\libntp\work_thread.c" />
+ <ClCompile Include="..\..\..\..\libntp\xsbprintf.c" />
<ClCompile Include="..\..\..\..\libntp\ymd2yd.c" />
<ClCompile Include="..\..\..\..\lib\isc\assertions.c" />
<ClCompile Include="..\..\..\..\lib\isc\backtrace-emptytbl.c" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<ClCompile Include="..\..\..\..\libntp\work_thread.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\..\libntp\xsbprintf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\..\libntp\ymd2yd.c">
<Filter>Source Files</Filter>
</ClCompile>
<Filter>Resource Files</Filter>
</CustomBuild>
</ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugXP|Win32">
<ClCompile Include="..\..\..\..\libntp\vint64ops.c" />
<ClCompile Include="..\..\..\..\libntp\work_fork.c" />
<ClCompile Include="..\..\..\..\libntp\work_thread.c" />
+ <ClCompile Include="..\..\..\..\libntp\xsbprintf.c" />
<ClCompile Include="..\..\..\..\libntp\ymd2yd.c" />
<ClCompile Include="..\..\..\..\lib\isc\assertions.c" />
<ClCompile Include="..\..\..\..\lib\isc\backtrace-emptytbl.c" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<ClCompile Include="..\..\..\..\libntp\work_thread.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\..\libntp\xsbprintf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\..\libntp\ymd2yd.c">
<Filter>Source Files</Filter>
</ClCompile>
<Filter>Resource Files</Filter>
</CustomBuild>
</ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
test-recvbuff \
test-refidsmear \
test-refnumtoa \
+ test-sbprintf \
test-sfptostr \
test-socktoa \
test-ssl_init \
$(srcdir)/run-recvbuff.c \
$(srcdir)/run-refidsmear.c \
$(srcdir)/run-refnumtoa.c \
+ $(srcdir)/run-sbprintf.c \
$(srcdir)/run-sfptostr.c \
$(srcdir)/run-socktoa.c \
$(srcdir)/run-ssl_init.c \
###
+test_sbprintf_SOURCES = \
+ sbprintf.c \
+ run-sbprintf.c \
+ $(NULL)
+
+$(srcdir)/run-sbprintf.c: $(srcdir)/sbprintf.c $(std_unity_list)
+ $(run_unity) $< $@
+
+###
+
test_sfptostr_SOURCES = \
sfptostr.c \
run-sfptostr.c \
--- /dev/null
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+//=======Test Runner Used To Run Each Test Below=====
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+ Unity.CurrentTestName = #TestFunc; \
+ Unity.CurrentTestLineNumber = TestLineNum; \
+ Unity.NumberOfTests++; \
+ if (TEST_PROTECT()) \
+ { \
+ setUp(); \
+ TestFunc(); \
+ } \
+ if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+ { \
+ tearDown(); \
+ } \
+ UnityConcludeTest(); \
+}
+
+//=======Automagically Detected Files To Include=====
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "config.h"
+#include "ntp_stdlib.h"
+#include <errno.h>
+
+//=======External Functions This Runner Calls=====
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_NullBuf1(void);
+extern void test_NullBuf2(void);
+extern void test_SmallBuf(void);
+extern void test_MatchBuf(void);
+extern void test_BigBuf(void);
+extern void test_SimpleArgs(void);
+
+
+//=======Suite Setup=====
+static void suite_setup(void)
+{
+extern int change_logfile(const char*, int);
+change_logfile("stderr", 0);
+}
+
+//=======Test Reset Option=====
+void resetTest(void);
+void resetTest(void)
+{
+ tearDown();
+ setUp();
+}
+
+char const *progname;
+
+
+//=======MAIN=====
+int main(int argc, char *argv[])
+{
+ progname = argv[0];
+ suite_setup();
+ UnityBegin("sbprintf.c");
+ RUN_TEST(test_NullBuf1, 7);
+ RUN_TEST(test_NullBuf2, 14);
+ RUN_TEST(test_SmallBuf, 23);
+ RUN_TEST(test_MatchBuf, 34);
+ RUN_TEST(test_BigBuf, 45);
+ RUN_TEST(test_SimpleArgs, 56);
+
+ return (UnityEnd());
+}
--- /dev/null
+#include "config.h"
+#include "ntp_stdlib.h"
+#include "unity.h"
+
+#include <errno.h>
+
+extern void test_NullBuf1(void);
+void test_NullBuf1(void)
+{
+ int rc = xsbprintf(NULL, NULL, "blah");
+ TEST_ASSERT(rc == -1 && errno == EINVAL);
+}
+
+extern void test_NullBuf2(void);
+void test_NullBuf2(void)
+{
+ char *bp = NULL;
+ int rc = xsbprintf(&bp, NULL, "blah");
+ TEST_ASSERT(rc == -1 && errno == EINVAL);
+ TEST_ASSERT_EQUAL_PTR(bp, NULL);
+}
+
+extern void test_SmallBuf(void);
+void test_SmallBuf(void)
+{
+ char ba[4];
+ char *bp = ba;
+ char *ep = ba + sizeof(ba);
+ int rc = xsbprintf(&bp, ep, "1234");
+ TEST_ASSERT(rc == 0 && strlen(ba) == 0);
+ TEST_ASSERT_EQUAL_PTR(bp, ba);
+}
+
+extern void test_MatchBuf(void);
+void test_MatchBuf(void)
+{
+ char ba[5];
+ char *bp = ba;
+ char *ep = ba + sizeof(ba);
+ int rc = xsbprintf(&bp, ep, "1234");
+ TEST_ASSERT(rc == 4 && strlen(ba) == 4);
+ TEST_ASSERT_EQUAL_PTR(bp, ba + 4);
+}
+
+extern void test_BigBuf(void);
+void test_BigBuf(void)
+{
+ char ba[10];
+ char *bp = ba;
+ char *ep = ba + sizeof(ba);
+ int rc = xsbprintf(&bp, ep, "1234");
+ TEST_ASSERT(rc == 4 && strlen(ba) == 4);
+ TEST_ASSERT_EQUAL_PTR(bp, ba + 4);
+}
+
+extern void test_SimpleArgs(void);
+void test_SimpleArgs(void)
+{
+ char ba[10];
+ char *bp = ba;
+ char *ep = ba + sizeof(ba);
+ int rc = xsbprintf(&bp, ep, "%d%d%d%d", 1, 2, 3, 4);
+ TEST_ASSERT(rc == 4 && strlen(ba) == 4);
+ TEST_ASSERT_EQUAL_PTR(bp, ba + 4);
+ TEST_ASSERT_FALSE(strcmp(ba, "1234"));
+}
+