The ANSI-C constant FILENAME_MAX is ludicrously small on some systems.
[u/mdw/putty] / misc.c
diff --git a/misc.c b/misc.c
index 59e91f2..9d71a8d 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <limits.h>
 #include <ctype.h>
 #include <assert.h>
 #include "putty.h"
@@ -23,7 +24,7 @@ unsigned long parse_blocksize(const char *bs)
     char *suf;
     unsigned long r = strtoul(bs, &suf, 10);
     if (*suf != '\0') {
-       while (isspace(*suf)) suf++;
+       while (*suf && isspace((unsigned char)*suf)) suf++;
        switch (*suf) {
          case 'k': case 'K':
            r *= 1024ul;
@@ -42,6 +43,50 @@ unsigned long parse_blocksize(const char *bs)
     return r;
 }
 
+/*
+ * Parse a ^C style character specification.
+ * Returns NULL in `next' if we didn't recognise it as a control character,
+ * in which case `c' should be ignored.
+ * The precise current parsing is an oddity inherited from the terminal
+ * answerback-string parsing code. All sequences start with ^; all except
+ * ^<123> are two characters. The ones that are worth keeping are probably:
+ *   ^?                    127
+ *   ^@A-Z[\]^_            0-31
+ *   a-z           1-26
+ *   <num>         specified by number (decimal, 0octal, 0xHEX)
+ *   ~             ^ escape
+ */
+char ctrlparse(char *s, char **next)
+{
+    char c = 0;
+    if (*s != '^') {
+       *next = NULL;
+    } else {
+       s++;
+       if (*s == '\0') {
+           *next = NULL;
+       } else if (*s == '<') {
+           s++;
+           c = (char)strtol(s, next, 0);
+           if ((*next == s) || (**next != '>')) {
+               c = 0;
+               *next = NULL;
+           } else
+               (*next)++;
+       } else if (*s >= 'a' && *s <= 'z') {
+           c = (*s - ('a' - 1));
+           *next = s+1;
+       } else if ((*s >= '@' && *s <= '_') || *s == '?' || (*s & 0x80)) {
+           c = ('@' ^ *s);
+           *next = s+1;
+       } else if (*s == '~') {
+           c = '^';
+           *next = s+1;
+       }
+    }
+    return c;
+}
+
 /* ----------------------------------------------------------------------
  * String handling routines.
  */
@@ -388,14 +433,21 @@ void mlog(char *file, int line)
 }
 #endif
 
-void *safemalloc(size_t size)
+void *safemalloc(size_t n, size_t size)
 {
     void *p;
+
+    if (n > INT_MAX / size) {
+       p = NULL;
+    } else {
+       size *= n;
 #ifdef MINEFIELD
-    p = minefield_c_malloc(size);
+       p = minefield_c_malloc(size);
 #else
-    p = malloc(size);
+       p = malloc(size);
 #endif
+    }
+
     if (!p) {
        char str[200];
 #ifdef MALLOC_LOG
@@ -415,22 +467,29 @@ void *safemalloc(size_t size)
     return p;
 }
 
-void *saferealloc(void *ptr, size_t size)
+void *saferealloc(void *ptr, size_t n, size_t size)
 {
     void *p;
-    if (!ptr) {
+
+    if (n > INT_MAX / size) {
+       p = NULL;
+    } else {
+       size *= n;
+       if (!ptr) {
 #ifdef MINEFIELD
-       p = minefield_c_malloc(size);
+           p = minefield_c_malloc(size);
 #else
-       p = malloc(size);
+           p = malloc(size);
 #endif
-    } else {
+       } else {
 #ifdef MINEFIELD
-       p = minefield_c_realloc(ptr, size);
+           p = minefield_c_realloc(ptr, size);
 #else
-       p = realloc(ptr, size);
+           p = realloc(ptr, size);
 #endif
+       }
     }
+
     if (!p) {
        char str[200];
 #ifdef MALLOC_LOG