From 3a2d225682d79f79c84852dbcb98d54cb250d62f Mon Sep 17 00:00:00 2001 From: Sebastian Marsching Date: Sat, 22 Jul 2023 08:27:32 -0700 Subject: [PATCH] Detect error in fprintf and return (fixes #309). fprintf returns a negative value in order to signal an error. We have to detect this situation in epicsStrPrintEscaped and return a negative when fprintf returns a negative value in order to give the calling code a chance to detect this situation. The old implementation (of simply accumulating the return values of fprintf) was wrong anyway, because it would not only lead to an error in fprintf to be lost but would also cause the returned number to be too small (not representing the actual number of bytes written) in such a case. The only case where the old implementation would work correctly was when all calls to fprintf succeeded or all these calls failed. --- modules/libcom/src/misc/epicsString.c | 36 ++++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/modules/libcom/src/misc/epicsString.c b/modules/libcom/src/misc/epicsString.c index ca61d9b8c..bcd10a504 100644 --- a/modules/libcom/src/misc/epicsString.c +++ b/modules/libcom/src/misc/epicsString.c @@ -231,27 +231,39 @@ int epicsStrPrintEscaped(FILE *fp, const char *s, size_t len) { int nout = 0; + if (fp == NULL) + return -1; + + if (s == NULL || strlen(s) == 0 || len == 0) + return 0; // No work to do + while (len--) { char c = *s++; + int rc = 0; switch (c) { - case '\a': nout += fprintf(fp, "\\a"); break; - case '\b': nout += fprintf(fp, "\\b"); break; - case '\f': nout += fprintf(fp, "\\f"); break; - case '\n': nout += fprintf(fp, "\\n"); break; - case '\r': nout += fprintf(fp, "\\r"); break; - case '\t': nout += fprintf(fp, "\\t"); break; - case '\v': nout += fprintf(fp, "\\v"); break; - case '\\': nout += fprintf(fp, "\\\\"); break; - case '\'': nout += fprintf(fp, "\\'"); break; - case '\"': nout += fprintf(fp, "\\\""); break; + case '\a': rc = fprintf(fp, "\\a"); break; + case '\b': rc = fprintf(fp, "\\b"); break; + case '\f': rc = fprintf(fp, "\\f"); break; + case '\n': rc = fprintf(fp, "\\n"); break; + case '\r': rc = fprintf(fp, "\\r"); break; + case '\t': rc = fprintf(fp, "\\t"); break; + case '\v': rc = fprintf(fp, "\\v"); break; + case '\\': rc = fprintf(fp, "\\\\"); break; + case '\'': rc = fprintf(fp, "\\'"); break; + case '\"': rc = fprintf(fp, "\\\""); break; default: if (isprint(0xff & (int)c)) - nout += fprintf(fp, "%c", c); + rc = fprintf(fp, "%c", c); else - nout += fprintf(fp, "\\x%02x", (unsigned char)c); + rc = fprintf(fp, "\\x%02x", (unsigned char)c); break; } + if (rc < 0) { + return rc; + } else { + nout += rc; + } } return nout; }