mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Changed the memory allocation strategy for NmapOutputTable from
estimating the worst-possible-case memory usage (the longest row length times the number of rows) to a more reasonable dynamic allocation of memory. Now the buffer is started at 512 bytes and approximately doubled each time it fills. 512 bytes is a compromise that was determined empirically. Most regular scans use less than 512 bytes. Scans with -sV and especially -sC tend to use a few k of memory. See http://seclists.org/nmap-dev/2009/q1/0782.html for the tests.
This commit is contained in:
@@ -214,33 +214,6 @@ void NmapOutputTable::addItemFormatted(unsigned int row,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the maximum size neccessary to create a printableTable() (the
|
|
||||||
// actual size could be less);
|
|
||||||
int NmapOutputTable::printableSize() {
|
|
||||||
|
|
||||||
struct NmapOutputTableCell *cell;
|
|
||||||
int rowlen = 0;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for(i = 0; i < numColumns; i++) {
|
|
||||||
rowlen += maxColLen[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the delimeter between each column, and the final newline */
|
|
||||||
rowlen += numColumns;
|
|
||||||
|
|
||||||
// if one of the fullrow tables is larger than the single column
|
|
||||||
// roles then the maximal rowlen needs to be adjusted.
|
|
||||||
for(i = 0; i < numRows; i++) {
|
|
||||||
cell = getCellAddy(i, 0);
|
|
||||||
if(cell->fullrow && cell->strlength + 1 > rowlen)
|
|
||||||
rowlen = cell->strlength + 1; /* Account for the newline with the +1 */
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowlen * numRows;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* True if every column in nrow is empty */
|
/* True if every column in nrow is empty */
|
||||||
bool NmapOutputTable::emptyRow(unsigned int nrow) {
|
bool NmapOutputTable::emptyRow(unsigned int nrow) {
|
||||||
NmapOutputTableCell *cell;
|
NmapOutputTableCell *cell;
|
||||||
@@ -267,18 +240,16 @@ bool NmapOutputTable::emptyRow(unsigned int nrow) {
|
|||||||
// All blank rows are removed from the returned string
|
// All blank rows are removed from the returned string
|
||||||
char *NmapOutputTable::printableTable(int *size) {
|
char *NmapOutputTable::printableTable(int *size) {
|
||||||
unsigned int col, row;
|
unsigned int col, row;
|
||||||
int maxsz = printableSize();
|
int p = 0; /* The offset into tableout */
|
||||||
char *p;
|
|
||||||
int clen = 0;
|
int clen = 0;
|
||||||
int i;
|
int i;
|
||||||
struct NmapOutputTableCell *cell;
|
struct NmapOutputTableCell *cell;
|
||||||
int validthisrow;
|
int validthisrow;
|
||||||
|
|
||||||
if (maxsz >= tableoutsz) {
|
if (tableoutsz == 0) {
|
||||||
tableoutsz = maxsz + 1;
|
tableoutsz = 512; /* Start us off with half a k */
|
||||||
tableout = (char *) safe_realloc(tableout, tableoutsz);
|
tableout = (char *) safe_malloc(tableoutsz);
|
||||||
}
|
}
|
||||||
p = tableout;
|
|
||||||
|
|
||||||
for(row = 0; row < numRows; row++) {
|
for(row = 0; row < numRows; row++) {
|
||||||
validthisrow = 0;
|
validthisrow = 0;
|
||||||
@@ -288,27 +259,38 @@ char *NmapOutputTable::printableTable(int *size) {
|
|||||||
|
|
||||||
cell = getCellAddy(row, 0);
|
cell = getCellAddy(row, 0);
|
||||||
if(cell->fullrow && cell->strlength > 0) {
|
if(cell->fullrow && cell->strlength > 0) {
|
||||||
memcpy(p, cell->str, cell->strlength);
|
/* Full rows are easy, just make sure we have the space + \n\0 */
|
||||||
|
if (cell->strlength + p + 2 > tableoutsz) {
|
||||||
|
tableoutsz = (cell->strlength + p + 2) * 2;
|
||||||
|
tableout = (char *) safe_realloc(tableout, tableoutsz);
|
||||||
|
}
|
||||||
|
memcpy(tableout + p, cell->str, cell->strlength);
|
||||||
p += cell->strlength;
|
p += cell->strlength;
|
||||||
} else {
|
} else {
|
||||||
for(col = 0; col < numColumns; col++) {
|
for(col = 0; col < numColumns; col++) {
|
||||||
cell = getCellAddy(row, col);
|
cell = getCellAddy(row, col);
|
||||||
clen = maxColLen[col];
|
clen = maxColLen[col];
|
||||||
|
/* Cells get padded with an extra space + \n\0 */
|
||||||
|
if (clen + p + 3 > tableoutsz) {
|
||||||
|
tableoutsz = (cell->strlength + p + 2) * 2;
|
||||||
|
tableout = (char *) safe_realloc(tableout, tableoutsz);
|
||||||
|
}
|
||||||
if (cell->strlength > 0) {
|
if (cell->strlength > 0) {
|
||||||
memcpy(p, cell->str, cell->strlength);
|
memcpy(tableout + p, cell->str, cell->strlength);
|
||||||
p += cell->strlength;
|
p += cell->strlength;
|
||||||
validthisrow++;
|
validthisrow++;
|
||||||
}
|
}
|
||||||
// No point leaving trailing spaces ...
|
// No point leaving trailing spaces ...
|
||||||
if (validthisrow < itemsInRow[row]) {
|
if (validthisrow < itemsInRow[row]) {
|
||||||
for(i=cell->strlength; i <= clen; i++) // one extra because of space between columns
|
for(i=cell->strlength; i <= clen; i++) // one extra because of space between columns
|
||||||
*(p++) = ' ';
|
*(tableout + p++) = ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(p++) = '\n';
|
*(tableout + p++) = '\n';
|
||||||
}
|
}
|
||||||
*p = '\0';
|
*(tableout + p) = '\0';
|
||||||
if (size) *size = p - tableout;
|
|
||||||
|
if (size) *size = p;
|
||||||
return tableout;
|
return tableout;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,10 +142,6 @@ class NmapOutputTable {
|
|||||||
void addItemFormatted(unsigned int row, unsigned int column, bool fullrow, const char *fmt, ...)
|
void addItemFormatted(unsigned int row, unsigned int column, bool fullrow, const char *fmt, ...)
|
||||||
__attribute__ ((format (printf, 4, 5)));
|
__attribute__ ((format (printf, 4, 5)));
|
||||||
|
|
||||||
// Returns the maximum size neccessary to create a printableTable() (the
|
|
||||||
// actual size could be less);
|
|
||||||
int printableSize();
|
|
||||||
|
|
||||||
// This function sticks the entire table into a character buffer.
|
// This function sticks the entire table into a character buffer.
|
||||||
// Note that the buffer is likely to be reused if you call the
|
// Note that the buffer is likely to be reused if you call the
|
||||||
// function again, and it will also be invalidated if you free the
|
// function again, and it will also be invalidated if you free the
|
||||||
|
|||||||
Reference in New Issue
Block a user