#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <limits.h>
#include <ctype.h>
#include <assert.h>
#include "putty.h"
+/*
+ * Parse a string block size specification. This is approximately a
+ * subset of the block size specs supported by GNU fileutils:
+ * "nk" = n kilobytes
+ * "nM" = n megabytes
+ * "nG" = n gigabytes
+ * All numbers are decimal, and suffixes refer to powers of two.
+ * Case-insensitive.
+ */
+unsigned long parse_blocksize(const char *bs)
+{
+ char *suf;
+ unsigned long r = strtoul(bs, &suf, 10);
+ if (*suf != '\0') {
+ while (*suf && isspace((unsigned char)*suf)) suf++;
+ switch (*suf) {
+ case 'k': case 'K':
+ r *= 1024ul;
+ break;
+ case 'm': case 'M':
+ r *= 1024ul * 1024ul;
+ break;
+ case 'g': case 'G':
+ r *= 1024ul * 1024ul * 1024ul;
+ break;
+ case '\0':
+ default:
+ break;
+ }
+ }
+ 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.
*/
}
}
+/*
+ * Read an entire line of text from a file. Return a buffer
+ * malloced to be as big as necessary (caller must free).
+ */
+char *fgetline(FILE *fp)
+{
+ char *ret = snewn(512, char);
+ int size = 512, len = 0;
+ while (fgets(ret + len, size - len, fp)) {
+ len += strlen(ret + len);
+ if (ret[len-1] == '\n')
+ break; /* got a newline, we're done */
+ size = len + 512;
+ ret = sresize(ret, size, char);
+ }
+ if (len == 0) { /* first fgets returned NULL */
+ sfree(ret);
+ return NULL;
+ }
+ ret[len] = '\0';
+ return ret;
+}
+
/* ----------------------------------------------------------------------
* Base64 encoding routine. This is required in public-key writing
* but also in HTTP proxy handling, so it's centralised here.
}
#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;
+ if (size == 0) size = 1;
#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
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