@cryptotaxi247 / netdata-1 / commits / 78f7cd502

replaced all sprintf with snprintf to guarantee thre is no buffer overflow possible

Costa Tsaousis (ktsaou) committed Apr 27, 2014 at 16:07 UTC 78f7cd5022619ee477ff85111f82854a9bc352d5
1 file changed +93 -93
netdata.c
+93 -93
@@ -179,22 +179,20 @@ void log_date()
179 fprintf(stderr, "%s: ", outstr);
180 }
181
182 -#define debug(args...) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args)
182 +int debug_variable;
183 +//#define debug(args...) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args)
184 +#define debug(type, args...) do { if(!silent && debug_flags & type) debug_int(__FILE__, __FUNCTION__, __LINE__, type, ##args); } while(0)
185
186 void debug_int( const char *file, const char *function, const unsigned long line, unsigned long type, const char *fmt, ... )
187 {
186 - if(silent) return;
187 -
188 va_list args;
189
190 - if(debug_flags & type) {
191 - log_date();
192 - va_start( args, fmt );
193 - fprintf(stderr, "DEBUG (%04lu@%-15.15s): ", line, function);
194 - vfprintf( stderr, fmt, args );
195 - va_end( args );
196 - fprintf(stderr, "\n");
197 - }
190 + log_date();
191 + va_start( args, fmt );
192 + fprintf(stderr, "DEBUG (%04lu@%-15.15s): ", line, function);
193 + vfprintf( stderr, fmt, args );
194 + va_end( args );
195 + fprintf(stderr, "\n");
196 }
197
198 #define error(args...) error_int(__FILE__, __FUNCTION__, __LINE__, ##args)
@@ -1097,6 +1095,8 @@ struct web_buffer {
1095 time_t date; // the date this content has been generated
1096 };
1097
1098 +#define web_buffer_printf(wb, args...) wb->bytes += snprintf(&wb->buffer[wb->bytes], (wb->size - wb->bytes), ##args)
1099 +
1100 struct web_buffer *web_buffer_create(size_t size)
1101 {
1102 struct web_buffer *b;
@@ -1283,26 +1283,26 @@ unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer
1283 size_t first_entry = rrd_stats_first_entry(st);
1284 time_t first_entry_t = st->times[first_entry].tv_sec;
1285
1286 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t{\n");
1287 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"id\" : \"%s\",\n", st->id);
1288 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"name\" : \"%s\",\n", st->name);
1289 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"type\" : \"%s\",\n", st->type);
1290 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"group_tag\" : \"%s\",\n", st->group);
1291 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"title\" : \"%s\",\n", st->title);
1292 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"title\" : \"%s\",\n", st->usertitle);
1293 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"priority\" : %ld,\n", st->userpriority);
1294 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"enabled\" : %d,\n", st->enabled);
1295 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"units\" : \"%s\",\n", st->units);
1296 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"url\" : \"/data/%s/%s\",\n", st->name, options?options:"");
1297 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"entries\" : %ld,\n", st->entries);
1298 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"first_entry\" : %ld,\n", first_entry);
1299 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"first_entry_t\" : %ld,\n", first_entry_t);
1300 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry\" : %ld,\n", st->current_entry);
1301 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry_t\" : %lu,\n", st->last_updated);
1302 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry_secs_ago\" : %lu,\n", time(NULL) - st->last_updated);
1303 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"update_every\" : %d,\n", update_every);
1304 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"isdetail\" : %d,\n", st->isdetail);
1305 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"dimensions\" : [\n");
1286 + web_buffer_printf(wb, "\t\t{\n");
1287 + web_buffer_printf(wb, "\t\t\t\"id\" : \"%s\",\n", st->id);
1288 + web_buffer_printf(wb, "\t\t\t\"name\" : \"%s\",\n", st->name);
1289 + web_buffer_printf(wb, "\t\t\t\"type\" : \"%s\",\n", st->type);
1290 + web_buffer_printf(wb, "\t\t\t\"group_tag\" : \"%s\",\n", st->group);
1291 + //web_buffer_printf(wb, "\t\t\t\"title\" : \"%s\",\n", st->title);
1292 + web_buffer_printf(wb, "\t\t\t\"title\" : \"%s\",\n", st->usertitle);
1293 + web_buffer_printf(wb, "\t\t\t\"priority\" : %ld,\n", st->userpriority);
1294 + web_buffer_printf(wb, "\t\t\t\"enabled\" : %d,\n", st->enabled);
1295 + web_buffer_printf(wb, "\t\t\t\"units\" : \"%s\",\n", st->units);
1296 + web_buffer_printf(wb, "\t\t\t\"url\" : \"/data/%s/%s\",\n", st->name, options?options:"");
1297 + web_buffer_printf(wb, "\t\t\t\"entries\" : %ld,\n", st->entries);
1298 + //web_buffer_printf(wb, "\t\t\t\"first_entry\" : %ld,\n", first_entry);
1299 + web_buffer_printf(wb, "\t\t\t\"first_entry_t\" : %ld,\n", first_entry_t);
1300 + //web_buffer_printf(wb, "\t\t\t\"last_entry\" : %ld,\n", st->current_entry);
1301 + web_buffer_printf(wb, "\t\t\t\"last_entry_t\" : %lu,\n", st->last_updated);
1302 + //web_buffer_printf(wb, "\t\t\t\"last_entry_secs_ago\" : %lu,\n", time(NULL) - st->last_updated);
1303 + web_buffer_printf(wb, "\t\t\t\"update_every\" : %d,\n", update_every);
1304 + web_buffer_printf(wb, "\t\t\t\"isdetail\" : %d,\n", st->isdetail);
1305 + web_buffer_printf(wb, "\t\t\t\"dimensions\" : [\n");
1306
1307 unsigned long memory = sizeof(RRD_STATS) + (sizeof(struct timeval) * st->entries);
1308
@@ -1311,46 +1311,46 @@ unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer
1311 unsigned long rdmem = sizeof(RRD_DIMENSION) + (rd->bytes * rd->entries);
1312 memory += rdmem;
1313
1314 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t{\n");
1315 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"id\" : \"%s\",\n", rd->id);
1316 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"name\" : \"%s\",\n", rd->name);
1317 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"bytes\" : %ld,\n", rd->bytes);
1318 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"entries\" : %ld,\n", rd->entries);
1319 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"isSigned\" : %d,\n", rd->issigned);
1320 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"isHidden\" : %d,\n", rd->hidden);
1314 + web_buffer_printf(wb, "\t\t\t\t{\n");
1315 + web_buffer_printf(wb, "\t\t\t\t\t\"id\" : \"%s\",\n", rd->id);
1316 + web_buffer_printf(wb, "\t\t\t\t\t\"name\" : \"%s\",\n", rd->name);
1317 + //web_buffer_printf(wb, "\t\t\t\t\t\"bytes\" : %ld,\n", rd->bytes);
1318 + //web_buffer_printf(wb, "\t\t\t\t\t\"entries\" : %ld,\n", rd->entries);
1319 + web_buffer_printf(wb, "\t\t\t\t\t\"isSigned\" : %d,\n", rd->issigned);
1320 + web_buffer_printf(wb, "\t\t\t\t\t\"isHidden\" : %d,\n", rd->hidden);
1321
1322 switch(rd->type) {
1323 case RRD_DIMENSION_INCREMENTAL:
1324 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "incremental");
1324 + web_buffer_printf(wb, "\t\t\t\t\t\"type\" : \"%s\",\n", "incremental");
1325 break;
1326
1327 case RRD_DIMENSION_ABSOLUTE:
1328 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "absolute");
1328 + web_buffer_printf(wb, "\t\t\t\t\t\"type\" : \"%s\",\n", "absolute");
1329 break;
1330
1331 case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
1332 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "percent on incremental total");
1332 + web_buffer_printf(wb, "\t\t\t\t\t\"type\" : \"%s\",\n", "percent on incremental total");
1333 break;
1334
1335 case RRD_DIMENSION_PCENT_OVER_ROW_TOTAL:
1336 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "percent on absolute total");
1336 + web_buffer_printf(wb, "\t\t\t\t\t\"type\" : \"%s\",\n", "percent on absolute total");
1337 break;
1338
1339 default:
1340 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : %d,\n", rd->type);
1340 + web_buffer_printf(wb, "\t\t\t\t\t\"type\" : %d,\n", rd->type);
1341 break;
1342 }
1343
1344 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"multiplier\" : %ld,\n", rd->multiplier);
1345 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"divisor\" : %ld,\n", rd->divisor);
1346 - //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"last_entry_t\" : %lu,\n", rd->last_updated);
1347 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"memory\" : %lu\n", rdmem);
1348 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t}%s\n", rd->next?",":"");
1344 + //web_buffer_printf(wb, "\t\t\t\t\t\"multiplier\" : %ld,\n", rd->multiplier);
1345 + //web_buffer_printf(wb, "\t\t\t\t\t\"divisor\" : %ld,\n", rd->divisor);
1346 + //web_buffer_printf(wb, "\t\t\t\t\t\"last_entry_t\" : %lu,\n", rd->last_updated);
1347 + web_buffer_printf(wb, "\t\t\t\t\t\"memory\" : %lu\n", rdmem);
1348 + web_buffer_printf(wb, "\t\t\t\t}%s\n", rd->next?",":"");
1349 }
1350
1351 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t],\n");
1352 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"memory\" : %lu\n", memory);
1353 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t}");
1351 + web_buffer_printf(wb, "\t\t\t],\n");
1352 + web_buffer_printf(wb, "\t\t\t\"memory\" : %lu\n", memory);
1353 + web_buffer_printf(wb, "\t\t}");
1354
1355 pthread_mutex_unlock(&st->mutex);
1356 return memory;
@@ -1363,35 +1363,35 @@ void rrd_stats_graph_json(RRD_STATS *st, char *options, struct web_buffer *wb)
1363 {
1364 web_buffer_increase(wb, 16384);
1365
1366 - wb->bytes += sprintf(&wb->buffer[wb->bytes], RRD_GRAPH_JSON_HEADER);
1366 + web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
1367 rrd_stats_one_json(st, options, wb);
1368 - wb->bytes += sprintf(&wb->buffer[wb->bytes], RRD_GRAPH_JSON_FOOTER);
1368 + web_buffer_printf(wb, RRD_GRAPH_JSON_FOOTER);
1369 }
1370
1371 void rrd_stats_all_json(struct web_buffer *wb)
1372 {
1373 - web_buffer_increase(wb, 150000);
1373 + web_buffer_increase(wb, 1024);
1374
1375 unsigned long memory = 0;
1376 size_t c;
1377 RRD_STATS *st;
1378
1379 - wb->bytes += sprintf(&wb->buffer[wb->bytes], RRD_GRAPH_JSON_HEADER);
1379 + web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
1380
1381 for(st = root, c = 0; st ; st = st->next) {
1382 if(st->enabled) {
1383 - if(c) wb->bytes += sprintf(&wb->buffer[wb->bytes], "%s", ",\n");
1383 + if(c) web_buffer_printf(wb, "%s", ",\n");
1384 memory += rrd_stats_one_json(st, NULL, wb);
1385 c++;
1386 }
1387 }
1388
1389 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n\t],\n");
1390 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"hostname\": \"%s\",\n", hostname);
1391 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"update_every\": %d,\n", update_every);
1392 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"history\": %d,\n", save_history);
1393 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"memory\": %lu\n", memory);
1394 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "}\n");
1389 + web_buffer_printf(wb, "\n\t],\n");
1390 + web_buffer_printf(wb, "\t\"hostname\": \"%s\",\n", hostname);
1391 + web_buffer_printf(wb, "\t\"update_every\": %d,\n", update_every);
1392 + web_buffer_printf(wb, "\t\"history\": %d,\n", save_history);
1393 + web_buffer_printf(wb, "\t\"memory\": %lu\n", memory);
1394 + web_buffer_printf(wb, "}\n");
1395 }
1396
1397 long double rrd_stats_dimension_get(RRD_DIMENSION *rd, size_t position)
@@ -1484,7 +1484,7 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1484
1485 if(!dimensions) {
1486 pthread_mutex_unlock(&st->mutex);
1487 - wb->bytes = sprintf(wb->buffer, "No dimensions yet.");
1487 + web_buffer_printf(wb, "No dimensions yet.");
1488 return 0;
1489 }
1490
@@ -1501,10 +1501,10 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1501 group_values[c] = 0;
1502
1503 // print the labels
1504 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "{\n %scols%s:\n [\n", kq, kq);
1505 - wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1506 - wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1507 - wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1504 + web_buffer_printf(wb, "{\n %scols%s:\n [\n", kq, kq);
1505 + web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1506 + web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1507 + web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1508
1509 // print the header for each dimension
1510 // and update the print_hidden array for the dimensions that should be hidden
@@ -1513,12 +1513,12 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1513 print_hidden[c] = 1;
1514 else {
1515 print_hidden[c] = 0;
1516 - wb->bytes += sprintf(&wb->buffer[wb->bytes], ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1516 + web_buffer_printf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1517 }
1518 }
1519
1520 // print the begin of row data
1521 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ],\n %srows%s:\n [\n", kq, kq);
1521 + web_buffer_printf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
1522
1523 // make sure current_entry is within limits
1524 if(current_entry < 0 || current_entry >= st->entries) current_entry = 0;
@@ -1594,7 +1594,7 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1594 if(st->times[t].tv_sec > last_timestamp) last_timestamp = st->times[t].tv_sec;
1595
1596 sprintf(dtm, "Date(%d, %d, %d, %d, %d, %d, %d)", tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(st->times[t].tv_usec / 1000)); // datetime
1597 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "%s {%sc%s:[{%sv%s:%s%s%s}", printed?"]},\n":"", kq, kq, kq, kq, sq, dtm, sq);
1597 + web_buffer_printf(wb, "%s {%sc%s:[{%sv%s:%s%s%s}", printed?"]},\n":"", kq, kq, kq, kq, sq, dtm, sq);
1598
1599 print_this = 1;
1600 }
@@ -1677,15 +1677,15 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1677
1678 for(c = 0 ; c < dimensions ; c++) {
1679 if(!print_hidden[c])
1680 - wb->bytes += sprintf(&wb->buffer[wb->bytes], ",{%sv%s:%0.1Lf}", kq, kq, print_values[c]);
1680 + web_buffer_printf(wb, ",{%sv%s:%0.1Lf}", kq, kq, print_values[c]);
1681 }
1682
1683 printed++;
1684 }
1685 }
1686
1687 - if(printed) wb->bytes += sprintf(&wb->buffer[wb->bytes], "]}");
1688 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ]\n}\n");
1687 + if(printed) web_buffer_printf(wb, "]}");
1688 + web_buffer_printf(wb, "\n ]\n}\n");
1689
1690 debug(D_RRD_STATS, "RRD_STATS_JSON: %s Generated %ld rows, total %ld bytes", st->name, printed, wb->bytes);
1691
@@ -1700,15 +1700,15 @@ void generate_config(struct web_buffer *wb)
1700
1701 for(co = config_root; co ; co = co->next) {
1702 web_buffer_increase(wb, CONFIG_MAX_NAME + 4);
1703 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n[%s]\n", co->name);
1703 + web_buffer_printf(wb, "\n[%s]\n", co->name);
1704
1705 for(cv = co->values; cv ; cv = cv->next) {
1706 if(!cv->used) {
1707 web_buffer_increase(wb, CONFIG_MAX_NAME + 200);
1708 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t# the option '%s' is not used, you can remove it\n", cv->name);
1708 + web_buffer_printf(wb, "\t# the option '%s' is not used, you can remove it\n", cv->name);
1709 }
1710 web_buffer_increase(wb, CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 5);
1711 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t%s = %s\n", cv->name, cv->value);
1711 + web_buffer_printf(wb, "\t%s = %s\n", cv->name, cv->value);
1712 }
1713 }
1714 }
@@ -1729,7 +1729,7 @@ int mysendfile(struct web_client *w, char *filename)
1729 // if the filename contains a / or a .., refuse to serve it
1730 if(strstr(filename, "/") != 0 || strstr(filename, "..") != 0) {
1731 debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
1732 - w->data->bytes = sprintf(w->data->buffer, "File '%s' cannot be served. Filenames cannot contain / or ..", filename);
1732 + web_buffer_printf(w->data, "File '%s' cannot be served. Filenames cannot contain / or ..", filename);
1733 return 400;
1734 }
1735
@@ -1743,14 +1743,14 @@ int mysendfile(struct web_client *w, char *filename)
1743 struct stat stat;
1744 if(lstat(webfilename, &stat) != 0) {
1745 debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, filename);
1746 - w->data->bytes = sprintf(w->data->buffer, "File '%s' does not exist, or is not accessible.", filename);
1746 + web_buffer_printf(w->data, "File '%s' does not exist, or is not accessible.", filename);
1747 return 404;
1748 }
1749
1750 // check if the file is owned by us
1751 if(stat.st_uid != getuid() && stat.st_uid != geteuid()) {
1752 error("%llu: File '%s' is owned by user %d (I run as user %d). Access Denied.", w->id, filename, stat.st_uid, getuid());
1753 - w->data->bytes = sprintf(w->data->buffer, "Access to file '%s' is not permitted.", filename);
1753 + web_buffer_printf(w->data, "Access to file '%s' is not permitted.", filename);
1754 return 403;
1755 }
1756
@@ -1761,13 +1761,13 @@ int mysendfile(struct web_client *w, char *filename)
1761
1762 if(errno == EBUSY || errno == EAGAIN) {
1763 error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, filename);
1764 - sprintf(w->response_header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
1765 - w->data->bytes = sprintf(w->data->buffer, "The file '%s' is currently busy. Please try again later.", filename);
1764 + snprintf(w->response_header, MAX_HTTP_HEADER_SIZE, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
1765 + web_buffer_printf(w->data, "The file '%s' is currently busy. Please try again later.", filename);
1766 return 307;
1767 }
1768 else {
1769 error("%llu: Cannot open file '%s'.", w->id, filename);
1770 - w->data->bytes = sprintf(w->data->buffer, "Cannot open file '%s'.", filename);
1770 + web_buffer_printf(w->data, "Cannot open file '%s'.", filename);
1771 return 404;
1772 }
1773 }
@@ -2158,7 +2158,7 @@ void web_client_process(struct web_client *w)
2158 RRD_STATS *st = root;
2159
2160 for ( ; st ; st = st->next )
2161 - w->data->bytes += sprintf(&w->data->buffer[w->data->bytes], "%s\n", st->name);
2161 + web_buffer_printf(w->data, "%s\n", st->name);
2162 }
2163 else if(strcmp(tok, "all.json") == 0) {
2164 code = 200;
@@ -2333,10 +2333,10 @@ void web_client_process(struct web_client *w)
2333 strcpy(custom_header, w->response_header);
2334
2335 size_t headerlen = 0;
2336 - headerlen += sprintf(&w->response_header[headerlen],
2336 + headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
2337 "HTTP/1.1 %d %s\r\n"
2338 "Connection: %s\r\n"
2339 - "Server: Data Collector HTTP Server\r\n"
2339 + "Server: NetData Embedded HTTP Server\r\n"
2340 "Content-Type: %s\r\n"
2341 "Access-Control-Allow-Origin: *\r\n"
2342 "Date: %s\r\n"
@@ -2347,24 +2347,24 @@ void web_client_process(struct web_client *w)
2347 );
2348
2349 if(custom_header[0])
2350 - headerlen += sprintf(&w->response_header[headerlen], "%s", custom_header);
2350 + headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen, "%s", custom_header);
2351
2352 if(w->mode == WEB_CLIENT_MODE_NORMAL) {
2353 - headerlen += sprintf(&w->response_header[headerlen],
2353 + headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
2354 "Expires: %s\r\n"
2355 "Cache-Control: no-cache\r\n"
2356 , date
2357 );
2358 }
2359 else {
2360 - headerlen += sprintf(&w->response_header[headerlen],
2360 + headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
2361 "Cache-Control: public\r\n"
2362 );
2363 }
2364
2365 // if we know the content length, put it
2366 if(!w->zoutput && (w->data->bytes || w->data->rbytes))
2367 - headerlen += sprintf(&w->response_header[headerlen],
2367 + headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
2368 "Content-Length: %ld\r\n"
2369 , w->data->bytes?w->data->bytes:w->data->rbytes
2370 );
@@ -2372,13 +2372,13 @@ void web_client_process(struct web_client *w)
2372 w->keepalive = 0; // content-length is required for keep-alive
2373
2374 if(w->zoutput) {
2375 - headerlen += sprintf(&w->response_header[headerlen],
2375 + headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
2376 "Content-Encoding: gzip\r\n"
2377 "Transfer-Encoding: chunked\r\n"
2378 );
2379 }
2380
2381 - headerlen += sprintf(&w->response_header[headerlen], "\r\n");
2381 + headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen, "\r\n");
2382
2383 // disable TCP_NODELAY, to buffer the header
2384 int flag = 0;
@@ -3187,7 +3187,7 @@ int do_proc_diskstats() {
3187 char ssfilename[FILENAME_MAX + 1];
3188 int sector_size = 512;
3189
3190 - sprintf(ssfilename, "/sys/block/%s/queue/hw_sector_size", disk);
3190 + snprintf(ssfilename, FILENAME_MAX, "/sys/block/%s/queue/hw_sector_size", disk);
3191 FILE *fpss = fopen(ssfilename, "r");
3192 if(fpss) {
3193 char ssbuffer[1025];
@@ -4969,7 +4969,7 @@ void *tc_main(void *ptr)
4969 struct tc_device *device = NULL;
4970 struct tc_class *class = NULL;
4971
4972 - sprintf(buffer, "exec %s %d", config_get("plugin:tc", "script", "./tc-all.sh"), update_every);
4972 + snprintf(buffer, TC_LINE_MAX, "exec %s %d", config_get("plugin:tc", "script", "./tc-all.sh"), update_every);
4973 fp = popen(buffer, "r");
4974
4975 while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {