- (void)makeDisplayList {
fp = fopen("...CoordinateGroups.txt", "r"); [COLOR="Red"]// opened but never closed[/COLOR]
fp2 = fopen("...Coordinates.txt", "r"); [COLOR="Red"]// opened but never closed[/COLOR]
char *line = (char *) malloc(50); [COLOR="Red"]// will be null when free()'ed; reassigned[/COLOR]
line = fgets(line, 50, fp); [COLOR="Red"]// may assign null; 50 is magic number[/COLOR]
char *lineNumber = (char *)malloc(5); [COLOR="Red"]// never freed; reassigned[/COLOR]
char *geometricType = (char *) malloc(1); [COLOR="Red"]// never freed; reassigned; inadequate length[/COLOR]
int num; [COLOR="Red"]// not used outside while block, should be declared inside that block[/COLOR]
glNewList(1, GL_COMPILE);
while (line) {
geometricType = strsep(&line, ";"); [COLOR="Red"]// reassigns to malloc'ed ptr[/COLOR]
num = strtol(geometricType, NULL, 10); [COLOR="Red"]// long assigned to int: may lose precision[/COLOR]
//This is for GL_QUADS. I have not yet added GL_TRIANGLES coordinate parsing code.
if (num == 4) {
float *coords1 = (float*)malloc(3*sizeof(float)); [COLOR="Red"]// never freed; reassigned[/COLOR]
float *coords2 = (float*)malloc(3*sizeof(float)); [COLOR="Red"]// never freed; reassigned[/COLOR]
float *coords3 = (float*)malloc(3*sizeof(float)); [COLOR="Red"]// never freed; reassigned[/COLOR]
float *coords4 = (float*)malloc(3*sizeof(float)); [COLOR="Red"]// never freed; reassigned[/COLOR]
for (int i = 0; i < 4; i++) {
lineNumber = strsep(&line, ",");
if(strlen(lineNumber) > 0) {
if(lineNumber[strlen(lineNumber)-1] == ';')
lineNumber[strlen(lineNumber)-1] = '\0';
} [COLOR="Red"]// no else clause, possible bug: what happens when strlen is 0?[/COLOR]
if (i == 0) { [COLOR="Red"]// use switch/case instead of if/else chain[/COLOR]
[self getCoords:strtol(lineNumber, NULL, 10) Array: &coords1];
printf("%f, %f, %f\n", coords1[0], coords1[1], coords1[2]);
} else if (i == 1) {
[self getCoords:strtol(lineNumber, NULL, 10) Array: &coords2];
printf("%f, %f, %f\n", coords2[0], coords2[1], coords2[2]);
} else if (i == 2) {
[self getCoords:strtol(lineNumber, NULL, 10) Array: &coords3];
printf("%f, %f, %f\n", coords3[0], coords3[1], coords3[2]);
} else {
[self getCoords:strtol(lineNumber, NULL, 10) Array: &coords4];
printf("%f, %f, %f\n", coords4[0], coords4[1], coords4[2]);
}
[COLOR="Red"]// In all the above blocks, no error-check is done on strtol(),[/COLOR]
[COLOR="Red"]// which returns 0 with errno=EINVAL on errors.[/COLOR]
[COLOR="Red"]// Every call to getCoords:Array: overwrites a malloc'ed ptr[/COLOR]
[COLOR="Red"]// with an out-of-scope ptr to a stack-local float[].[/COLOR]
}
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_QUADS);
{
glVertex3f(coords1[0], coords1[1], coords1[2]);
glVertex3f(coords2[0], coords2[1], coords2[2]);
glVertex3f(coords3[0], coords3[1], coords3[2]);
glVertex3f(coords4[0], coords4[1], coords4[2]);
}
glEnd();
}
line = fgets(line, 50, fp);
[COLOR="Red"]// This fgets() uses a value of line that was advanced by prior strsep() calls.[/COLOR]
[COLOR="Red"]// The sequential actions of strsep() will eventually advance line past the end[/COLOR]
[COLOR="Red"]// of the malloc'ed buffer, and subsequent fgets()'s will damage memory.[/COLOR]
}
glEndList();
free(line); [COLOR="Red"]// will always free null, since line is null after EOF from fgets()[/COLOR]
}
- (void) getCoords: (int) i Array: (float **) a {
rewind(fp2); [COLOR="Red"]// poor design choice: uses fp2 ivar instead of arg[/COLOR]
char line[50]; [COLOR="Red"]// magic number[/COLOR]
char *strptr = line;
for (int j = 0; j < i + 1; j++) {
strptr = fgets(strptr, 50, fp2); [COLOR="Red"]// doesn't break or return on null (EOF)[/COLOR]
}
char *x, *y, *z;
x = strsep(&strptr, ";");[COLOR="Red"]// 3X: doesn't handle null strptr [/COLOR]
y = strsep(&strptr, ";");
z = strsep(&strptr, ";");
float coords[] = {strtof(x, NULL), strtof(y, NULL), strtof(z, NULL)};[COLOR="Red"]// 3X: doesn't handle conversion failures[/COLOR]
*a = coords; [COLOR="Red"]// overwrites malloc'ed ptr; stores address of out-of-scope buffer[/COLOR]
}