Yeah, there's quite a few problems with that code, mostly memory allocation problems.
Some of your pointers would seem to be just small arrays used for copying short strings.
One major problem not addressed at all is that your new string will be longer than your old string, say an input of "999" is 3 characters, but with 15 added, the result of "1014" needs 4 characters.
Code:
static void CM_LoadEntityString(const byte * data, const lump_t * l)
{
char *game = Cvar_VariableString("fs_game");
int i, j, Tam, TamNew;
int PA, PB, PC, PD, PL, L1, Num, Espaco, Aspas;
char *p = NULL, *ori = NULL, *HStr = NULL, *NewStr = NULL, *FinalStr = NULL;
char *PartA = NULL, *PartB = NULL, *PartC = NULL, *PartD = NULL;
/*!! Set all pointers to NULL */
/*!! It will tell you with more consistency if you're messing with */
/*!! pointers before initialising them */
cm_numEntityChars = l->fileLen;
if (cm_numEntityChars < 1)
return;
if (cm_numEntityChars > MAX_MAP_ENTSTRING)
Com_Error(ERR_DROP,
"CM_LoadMap: map '%s' has too large entity lump",
cm_map);
cm_entityString = Hunk_Alloc(cm_numEntityChars + 1);
memcpy(cm_entityString, data + l->fileOfs, cm_numEntityChars);
/*!! If you need to make this a proper 'C' string, you need to add a \0 */
/*!! cm_entityString[cm_numEntityChars] = '\0'; */
// do string manipulation over cm_entityString if game = arena
if (!Q_stricmp(game, "arena")) {
HStr = cm_entityString; // copy the original string to mine
/*!! Not a copy, just another pointer to the same string */
/*!! anything you do to HStr[i] will change cm_entityString[i] */
Tam = strlen(HStr);
i = 0;
j = 0;
while (j < Tam) {
while ( HStr[j] != '}' ) { // copy to NewStr each Class
NewStr[i] = HStr[j];
/*!! First pointer violation - where is NewStr pointing? */
i++;
j++;
}
NewStr[i] = HStr[j]; //add '}' to the end of the class
p = strstr(NewStr, "info_player"); //see if is a spawn class
if (!p) {
FinalStr = strcat(FinalStr, NewStr); //if not, save and go to the next class
/*!! Second pointer violation - where is FinalStr pointing? */
} else {
//if yes, start the hard work
ori = strstr(NewStr, "origin"); //find the origin position
L1 = atoi(ori); // converted to number
/*!! no, that's just atoi("origin"), which makes no sense */
L1 += 8; // than add +8 (origin" ") to that position, which will reach the numbers of the axis
/*!! If you want to read the numbers, then it would be ori += 8 */
/*!! that is, 8 characters past the start of the word "origin" */
// find PartA from 0 to L1
for (PA = 0; PA == L1; PA++) //seta parte 1/4
{
PartA[PA] = NewStr[PA];
}
PL = PA; //creat a new var to control the place in NewStr
Espaco = 0; //set to have zero spaces count
// find PartB from start of numbers until 2nd space
for (PB = 0; Espaco != 2; PB++) //set part 2/4
{
PL++;
PartB[PB] = NewStr[PL];
if (PartB[PB] == " ")
Espaco++;
}
Aspas = 0; //set to plics to zero count
// find PartC which is the Number, until reach next "
for (PC = 0; Aspas == 1; PC++) //set part 3/4 = Num
{
PL++;
if (NewStr[PL] == '"')
Aspas = 1;
else
PartC[PC] = NewStr[PL];
}
TamNew = strlen(NewStr); //find the size of NewStr
// find PartD from " after number until the end of class
for (PD = 0; PL == TamNew; PD++) //set part 4/4
{
PartD[PD] = NewStr[PL];
PL++;
}
Num = atoi(PartC); // Convert to Number
Num += 15; //add 15
NewStr = strcat(PartA, PartB); // make all 4 parts into one
NewStr = strcat(NewStr, Num); // -- NEED TO CONVERT????!!!
/*!! Yes you do need to convert, using say sprintf() */
NewStr = strcat(NewStr, PartD);
FinalStr = strcat(FinalStr, NewStr); // add all NewStr to FinalStr
}
i = 0; //NewStr count to zero
j++;
NewStr = ""; //erase NewStr
/*!! This does not erase the string, it just makes it point somewhere else */
/*!! But since it was never allocated in the first place.... */
}
cm_entityString = FinalStr; //replace the original by the new altered one
/*!! As mentioned earlier, FinalStr was never allocated */
/*!! Also, you would probably need to do Hunk_Free(cm_entityString) */
/*!! before assigning it a new value */
}
}
Here's my test code and results
Code:
void foo ( const char *msg ) {
const char *p = msg;
while ( p != NULL ) {
char *origin = strstr( p, "origin" ); /* find origin */
if ( origin != NULL ) {
int x, y, z;
int n, len;
/* From the last position to the start of "origin" */
printf("Head='%.*s'\n", origin - p, p );
origin += 8;
n = sscanf( origin, "%*[\"] %d %d %d %*[\"] %n", &x, &y, &z, &len );
/* check n==3 for success */
printf("Posn=%d,%d,%d; len=%d\n", x, y, z, len );
/* Resume from the end of the processed origin */
p = origin + len;
} else {
printf("Tail='%s'\n", p );
p = NULL;
}
}
}
int main()
{
char test[] =
"{\"classname\" \"worldspawn\"}"
"{\"origin\" \"-256 248 16\"\"classname\" \"info_player_deathmatch\"}"
"{\"classname\" \"info_player_deathmatch\"\"origin\" \"248 256 16\"}"
"{\"origin\" \"248 -256 16\"\"classname\" \"info_player_deathmatch\"}"
"{\"classname\" \"info_player_deathmatch\"\"origin\" \"-264 -256 16\"}"
"{\"origin\" \"-176 -200 24\"\"classname\" \"weapon_rocketlauncher\"}"
"{\"classname\" \"weapon_rocketlauncher\"\"origin\" \"-184 192 24\"}"
"{\"origin\" \"168 184 24\"\"classname\" \"weapon_rocketlauncher\"}"
"{\"origin\" \"-184 -264 24\"\"classname\" \"ammo_rockets\"}"
"{\"classname\" \"ammo_rockets\"\"origin\" \"192 -256 24\"}"
"{\"origin\" \"184 128 24\"\"classname\" \"ammo_rockets\"}"
"{\"classname\" \"ammo_rockets\"\"origin\" \"-184 128 24\"}"
"{\"origin\" \"216 -192 24\"\"classname\" \"weapon_rocketlauncher\"}"
"{\"light\" \"400\"\"origin\" \"-8 0 208\"\"classname\" \"light\"}"
;
foo(test);
return 0;
}
$ gcc foo.c
$ ./a.exe
Head='{"classname" "worldspawn"}{"'
Posn=-256,248,16, len=14
Head='classname" "info_player_deathmatch"}{"classname" "info_player_deathmatch""'
Posn=248,256,16, len=12
Head='}{"'
Posn=248,-256,16, len=14
Head='classname" "info_player_deathmatch"}{"classname" "info_player_deathmatch""'
Posn=-264,-256,16, len=14
Head='}{"'
Posn=-176,-200,24, len=15
Head='classname" "weapon_rocketlauncher"}{"classname" "weapon_rocketlauncher""'
Posn=-184,192,24, len=13
Head='}{"'
Posn=168,184,24, len=13
Head='classname" "weapon_rocketlauncher"}{"'
Posn=-184,-264,24, len=15
Head='classname" "ammo_rockets"}{"classname" "ammo_rockets""'
Posn=192,-256,24, len=13
Head='}{"'
Posn=184,128,24, len=13
Head='classname" "ammo_rockets"}{"classname" "ammo_rockets""'
Posn=-184,128,24, len=13
Head='}{"'
Posn=216,-192,24, len=14
Head='classname" "weapon_rocketlauncher"}{"light" "400""'
Posn=-8,0,208, len=11
Tail='classname" "light"}'