Changeset: 6ed388bc827b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6ed388bc827b
Modified Files:
        monetdb5/mal/mal_exception.c
Branch: Jun2020
Log Message:

Avoid using large buffers on the stack.


diffs (136 lines):

diff --git a/monetdb5/mal/mal_exception.c b/monetdb5/mal/mal_exception.c
--- a/monetdb5/mal/mal_exception.c
+++ b/monetdb5/mal/mal_exception.c
@@ -61,22 +61,39 @@ dupError(const char *err)
 static str __attribute__((__format__(__printf__, 3, 0), __returns_nonnull__))
 createExceptionInternal(enum malexception type, const char *fcn, const char 
*format, va_list ap)
 {
-       char local[GDKMAXERRLEN];
+       size_t msglen;
        int len;
+       char *msg;
+       va_list ap2;
 #ifndef NDEBUG
        // if there is an error we allow memory allocation once again
        GDKsetmallocsuccesscount(-1);
 #endif
-       len = snprintf(local, GDKMAXERRLEN, "%s:%s:", exceptionNames[type], 
fcn);
-       len = vsnprintf(local + len, GDKMAXERRLEN - len, format, ap);
-       if (len < 0)
+       va_copy(ap2, ap);                       /* we need to use it twice */
+       msglen = strlen(exceptionNames[type]) + strlen(fcn) + 2;
+       len = vsnprintf(NULL, 0, format, ap); /* count necessary length */
+       if (len < 0) {
                TRC_CRITICAL(MAL_SERVER, "called with bad arguments");
-       char *q = local;
-       for (char *p = strchr(q, '\n'); p; q = p + 1, p = strchr(q, '\n'))
-               TRC_ERROR(MAL_SERVER, "%.*s\n", (int) (p - q), q);
-       if (*q)
-               TRC_ERROR(MAL_SERVER, "%s\n", q);
-       return dupError(local);
+               len = 0;
+       }
+       msg = GDKmalloc(msglen + len + 1);
+       if (msg != NULL) {
+               /* the calls below succeed: the arguments have already been 
checked */
+               (void) strconcat_len(msg, msglen + 1,
+                                                        exceptionNames[type], 
":", fcn, ":", NULL);
+               if (len > 0)
+                       (void) vsnprintf(msg + msglen, len + 1, format, ap2);
+               va_end(ap2);
+               char *q = msg;
+               for (char *p = strchr(msg, '\n'); p; q = p + 1, p = strchr(q, 
'\n'))
+                       TRC_ERROR(MAL_SERVER, "%.*s\n", (int) (p - q), q);
+               if (*q)
+                       TRC_ERROR(MAL_SERVER, "%s\n", q);
+       } else {
+               msg = M5OutOfMemory;
+       }
+       va_end(ap2);
+       return msg;
 }
 
 /**
@@ -145,38 +162,52 @@ freeException(str msg)
 static str __attribute__((__format__(__printf__, 5, 0), __returns_nonnull__))
 createMalExceptionInternal(MalBlkPtr mb, int pc, enum malexception type, char 
*prev, const char *format, va_list ap)
 {
-       char buf[GDKMAXERRLEN];
-       size_t i;
-       str s, fcn;
+       bool addnl = false;
+       const char *s = mb ? getModName(mb) : "unknown";
+       const char *fcn = mb ? getFcnName(mb) : "unknown";
+       size_t msglen;
 
-       s = mb ? getModName(mb) : "unknown";
-       fcn = mb ? getFcnName(mb) : "unknown";
-       i = 0;
-
-       if (prev){
-               if( *prev){
-                       i += snprintf(buf + i, GDKMAXERRLEN - 1 - i, "%s", 
prev);
-                       if( buf[i-1] != '\n')
-                               buf[i++]= '\n';
+       if (prev) {
+               msglen = strlen(prev);
+               if (msglen > 0 && prev[msglen - 1] != '\n') {
+                       addnl = true;
+                       msglen++;
                }
-               i += snprintf(buf + i, GDKMAXERRLEN - 1 - i, "!%s:%s.%s[%d]:",
-                               exceptionNames[type], s, fcn, pc);
-               freeException(prev);
-       } else if( type == SYNTAX)
-               i += snprintf(buf + i, GDKMAXERRLEN - 1 - i, "%s:",
-                               exceptionNames[type]);
-       else
-               i += snprintf(buf + i, GDKMAXERRLEN - 1 - i, "%s:%s.%s[%d]:",
-                               exceptionNames[type], s, fcn, pc);
-       i += vsnprintf(buf + i, GDKMAXERRLEN - 1 - i, format, ap);
-       if( buf[i-1] != '\n')
-               buf[i++]= '\n';
-       buf[i] = '\0';
-
-       s = GDKstrdup(buf);
-       if (s == NULL)                          /* make sure we always return 
something */
-               s = M5OutOfMemory;
-       return s;
+               msglen += snprintf(NULL, 0, "!%s:%s.%s[%d]:",
+                                                  exceptionNames[type], s, 
fcn, pc);
+       } else if (type == SYNTAX) {
+               msglen = strlen(exceptionNames[type]) + 1;
+       } else {
+               msglen = snprintf(NULL, 0, "%s:%s.%s[%d]:",
+                                                 exceptionNames[type], s, fcn, 
pc);
+       }
+       va_list ap2;
+       va_copy(ap2, ap);
+       int len = vsnprintf(NULL, 0, format, ap);
+       if (len < 0)
+               len = 0;
+       char *msg = GDKmalloc(msglen + len + 1);
+       if (msg != NULL) {
+               /* the calls below succeed: the arguments have already been 
checked */
+               if (prev) {
+                       (void) snprintf(msg, msglen + 1, "%s%s!%s:%s.%s[%d]:",
+                                                       prev, addnl ? "\n" : "",
+                                                       exceptionNames[type], 
s, fcn, pc);
+               } else if (type == SYNTAX) {
+                       (void) strconcat_len(msg, msglen + 1,
+                                                                
exceptionNames[type], ":", NULL);
+               } else {
+                       (void) snprintf(msg, msglen + 1, "%s:%s.%s[%d]:",
+                                                       exceptionNames[type], 
s, fcn, pc);
+               }
+               if (len > 0)
+                       (void) vsnprintf(msg + msglen, len + 1, format, ap2);
+       } else {
+               msg = M5OutOfMemory;
+       }
+       va_end(ap2);
+       freeException(prev);
+       return msg;
 }
 
 /**
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to