| OLD | NEW |
| 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 /* This Source Code Form is subject to the terms of the Mozilla Public | 2 /* This Source Code Form is subject to the terms of the Mozilla Public |
| 3 * License, v. 2.0. If a copy of the MPL was not distributed with this | 3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 5 | 5 |
| 6 /* | 6 /* |
| 7 ** Portable safe sprintf code. | 7 ** Portable safe sprintf code. |
| 8 ** | 8 ** |
| 9 ** Author: Kipp E.B. Hickman | 9 ** Author: Kipp E.B. Hickman |
| 10 */ | 10 */ |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 ** XXX This needs to be internationalized! | 30 ** XXX This needs to be internationalized! |
| 31 */ | 31 */ |
| 32 | 32 |
| 33 typedef struct SprintfStateStr SprintfState; | 33 typedef struct SprintfStateStr SprintfState; |
| 34 | 34 |
| 35 struct SprintfStateStr { | 35 struct SprintfStateStr { |
| 36 int (*stuff)(SprintfState *ss, const char *sp, PRUint32 len); | 36 int (*stuff)(SprintfState *ss, const char *sp, PRUint32 len); |
| 37 | 37 |
| 38 char *base; | 38 char *base; |
| 39 char *cur; | 39 char *cur; |
| 40 PRUint32 maxlen; | 40 PRUint32 maxlen; /* Must not exceed PR_INT32_MAX. */ |
| 41 | 41 |
| 42 int (*func)(void *arg, const char *sp, PRUint32 len); | 42 int (*func)(void *arg, const char *sp, PRUint32 len); |
| 43 void *arg; | 43 void *arg; |
| 44 }; | 44 }; |
| 45 | 45 |
| 46 /* | 46 /* |
| 47 ** Numbered Argument | 47 ** Numbered Argument |
| 48 */ | 48 */ |
| 49 struct NumArg { | 49 struct NumArg { |
| 50 int type; /* type of the numbered argument */ | 50 int type; /* type of the numbered argument */ |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 #ifdef WIN32 | 690 #ifdef WIN32 |
| 691 const WCHAR *ws; | 691 const WCHAR *ws; |
| 692 #endif | 692 #endif |
| 693 } u; | 693 } u; |
| 694 const char *fmt0; | 694 const char *fmt0; |
| 695 static char *hex = "0123456789abcdef"; | 695 static char *hex = "0123456789abcdef"; |
| 696 static char *HEX = "0123456789ABCDEF"; | 696 static char *HEX = "0123456789ABCDEF"; |
| 697 char *hexp; | 697 char *hexp; |
| 698 int rv, i; | 698 int rv, i; |
| 699 struct NumArg* nas = NULL; | 699 struct NumArg* nas = NULL; |
| 700 struct NumArg* nap; | 700 struct NumArg* nap = NULL; |
| 701 struct NumArg nasArray[ NAS_DEFAULT_NUM ]; | 701 struct NumArg nasArray[ NAS_DEFAULT_NUM ]; |
| 702 char pattern[20]; | 702 char pattern[20]; |
| 703 const char* dolPt = NULL; /* in "%4$.2f", dolPt will point to . */ | 703 const char* dolPt = NULL; /* in "%4$.2f", dolPt will point to . */ |
| 704 #ifdef WIN32 | 704 #ifdef WIN32 |
| 705 char *pBuf = NULL; | 705 char *pBuf = NULL; |
| 706 #endif | 706 #endif |
| 707 | 707 |
| 708 /* | 708 /* |
| 709 ** build an argument array, IF the fmt is numbered argument | 709 ** build an argument array, IF the fmt is numbered argument |
| 710 ** list style, to contain the Numbered Argument list pointers | 710 ** list style, to contain the Numbered Argument list pointers |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1053 | 1053 |
| 1054 return rv; | 1054 return rv; |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 /************************************************************************/ | 1057 /************************************************************************/ |
| 1058 | 1058 |
| 1059 static int FuncStuff(SprintfState *ss, const char *sp, PRUint32 len) | 1059 static int FuncStuff(SprintfState *ss, const char *sp, PRUint32 len) |
| 1060 { | 1060 { |
| 1061 int rv; | 1061 int rv; |
| 1062 | 1062 |
| 1063 /* |
| 1064 ** We will add len to ss->maxlen at the end of the function. First check |
| 1065 ** if ss->maxlen + len would overflow or be greater than PR_INT32_MAX. |
| 1066 */ |
| 1067 if (PR_UINT32_MAX - ss->maxlen < len || ss->maxlen + len > PR_INT32_MAX) { |
| 1068 return -1; |
| 1069 } |
| 1063 rv = (*ss->func)(ss->arg, sp, len); | 1070 rv = (*ss->func)(ss->arg, sp, len); |
| 1064 if (rv < 0) { | 1071 if (rv < 0) { |
| 1065 return rv; | 1072 return rv; |
| 1066 } | 1073 } |
| 1067 ss->maxlen += len; | 1074 ss->maxlen += len; |
| 1068 return 0; | 1075 return 0; |
| 1069 } | 1076 } |
| 1070 | 1077 |
| 1071 PR_IMPLEMENT(PRUint32) PR_sxprintf(PRStuffFunc func, void *arg, | 1078 PR_IMPLEMENT(PRUint32) PR_sxprintf(PRStuffFunc func, void *arg, |
| 1072 const char *fmt, ...) | 1079 const char *fmt, ...) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1098 ** Stuff routine that automatically grows the malloc'd output buffer | 1105 ** Stuff routine that automatically grows the malloc'd output buffer |
| 1099 ** before it overflows. | 1106 ** before it overflows. |
| 1100 */ | 1107 */ |
| 1101 static int GrowStuff(SprintfState *ss, const char *sp, PRUint32 len) | 1108 static int GrowStuff(SprintfState *ss, const char *sp, PRUint32 len) |
| 1102 { | 1109 { |
| 1103 ptrdiff_t off; | 1110 ptrdiff_t off; |
| 1104 char *newbase; | 1111 char *newbase; |
| 1105 PRUint32 newlen; | 1112 PRUint32 newlen; |
| 1106 | 1113 |
| 1107 off = ss->cur - ss->base; | 1114 off = ss->cur - ss->base; |
| 1115 if (PR_UINT32_MAX - len < off) { |
| 1116 /* off + len would be too big. */ |
| 1117 return -1; |
| 1118 } |
| 1108 if (off + len >= ss->maxlen) { | 1119 if (off + len >= ss->maxlen) { |
| 1109 /* Grow the buffer */ | 1120 /* Grow the buffer */ |
| 1110 » newlen = ss->maxlen + ((len > 32) ? len : 32); | 1121 » PRUint32 increment = (len > 32) ? len : 32; |
| 1122 » if (PR_UINT32_MAX - ss->maxlen < increment) { |
| 1123 » /* ss->maxlen + increment would overflow. */ |
| 1124 » return -1; |
| 1125 » } |
| 1126 » newlen = ss->maxlen + increment; |
| 1127 » if (newlen > PR_INT32_MAX) { |
| 1128 » return -1; |
| 1129 » } |
| 1111 if (ss->base) { | 1130 if (ss->base) { |
| 1112 newbase = (char*) PR_REALLOC(ss->base, newlen); | 1131 newbase = (char*) PR_REALLOC(ss->base, newlen); |
| 1113 } else { | 1132 } else { |
| 1114 newbase = (char*) PR_MALLOC(newlen); | 1133 newbase = (char*) PR_MALLOC(newlen); |
| 1115 } | 1134 } |
| 1116 if (!newbase) { | 1135 if (!newbase) { |
| 1117 /* Ran out of memory */ | 1136 /* Ran out of memory */ |
| 1118 return -1; | 1137 return -1; |
| 1119 } | 1138 } |
| 1120 ss->base = newbase; | 1139 ss->base = newbase; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 va_end(ap); | 1222 va_end(ap); |
| 1204 return rv; | 1223 return rv; |
| 1205 } | 1224 } |
| 1206 | 1225 |
| 1207 PR_IMPLEMENT(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen,const char *fmt, | 1226 PR_IMPLEMENT(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen,const char *fmt, |
| 1208 va_list ap) | 1227 va_list ap) |
| 1209 { | 1228 { |
| 1210 SprintfState ss; | 1229 SprintfState ss; |
| 1211 PRUint32 n; | 1230 PRUint32 n; |
| 1212 | 1231 |
| 1213 PR_ASSERT((PRInt32)outlen > 0); | 1232 PR_ASSERT(outlen != 0 && outlen <= PR_INT32_MAX); |
| 1214 if ((PRInt32)outlen <= 0) { | 1233 if (outlen == 0 || outlen > PR_INT32_MAX) { |
| 1215 return 0; | 1234 return 0; |
| 1216 } | 1235 } |
| 1217 | 1236 |
| 1218 ss.stuff = LimitStuff; | 1237 ss.stuff = LimitStuff; |
| 1219 ss.base = out; | 1238 ss.base = out; |
| 1220 ss.cur = out; | 1239 ss.cur = out; |
| 1221 ss.maxlen = outlen; | 1240 ss.maxlen = outlen; |
| 1222 (void) dosprintf(&ss, fmt, ap); | 1241 (void) dosprintf(&ss, fmt, ap); |
| 1223 | 1242 |
| 1224 /* If we added chars, and we didn't append a null, do it now. */ | 1243 /* If we added chars, and we didn't append a null, do it now. */ |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1240 return rv; | 1259 return rv; |
| 1241 } | 1260 } |
| 1242 | 1261 |
| 1243 PR_IMPLEMENT(char *) PR_vsprintf_append(char *last, const char *fmt, va_list ap) | 1262 PR_IMPLEMENT(char *) PR_vsprintf_append(char *last, const char *fmt, va_list ap) |
| 1244 { | 1263 { |
| 1245 SprintfState ss; | 1264 SprintfState ss; |
| 1246 int rv; | 1265 int rv; |
| 1247 | 1266 |
| 1248 ss.stuff = GrowStuff; | 1267 ss.stuff = GrowStuff; |
| 1249 if (last) { | 1268 if (last) { |
| 1250 » int lastlen = strlen(last); | 1269 » size_t lastlen = strlen(last); |
| 1270 » if (lastlen > PR_INT32_MAX) { |
| 1271 » return 0; |
| 1272 » } |
| 1251 ss.base = last; | 1273 ss.base = last; |
| 1252 ss.cur = last + lastlen; | 1274 ss.cur = last + lastlen; |
| 1253 ss.maxlen = lastlen; | 1275 ss.maxlen = lastlen; |
| 1254 } else { | 1276 } else { |
| 1255 ss.base = 0; | 1277 ss.base = 0; |
| 1256 ss.cur = 0; | 1278 ss.cur = 0; |
| 1257 ss.maxlen = 0; | 1279 ss.maxlen = 0; |
| 1258 } | 1280 } |
| 1259 rv = dosprintf(&ss, fmt, ap); | 1281 rv = dosprintf(&ss, fmt, ap); |
| 1260 if (rv < 0) { | 1282 if (rv < 0) { |
| 1261 if (ss.base) { | 1283 if (ss.base) { |
| 1262 PR_DELETE(ss.base); | 1284 PR_DELETE(ss.base); |
| 1263 } | 1285 } |
| 1264 return 0; | 1286 return 0; |
| 1265 } | 1287 } |
| 1266 return ss.base; | 1288 return ss.base; |
| 1267 } | 1289 } |
| 1268 | 1290 |
| OLD | NEW |