I'm still not sure, the cursor appears to be advancing as it should.
I tried this simpler function:
void replaceChar2(char* in, char inchar){
char* cpystr = "25";
char* p = strchr(in, inchar);
while (p != NULL) {
Serial.println("found");
Serial.println(in+(p-in));
memcpy(in+(p-in), cpystr, strlen(cpystr));
p = strchr(p, inchar);
}
}
And it still behaves badly only if the search char is '%', and the replace string contains a percent symbol at all. If the copy string has a '%', but the search char is not '%', or vice versa, it works, but when those cases are combined, it breaks.
Yup, in+(p-in) is indeed redundant, I changed it to just p.
In doing that I see that my while loop wasn't correct. as some had suggested it was in the fact that I was updating the pointer to the result of strchr(p, '%') when p itself was just set to '%' to the loop never ended. I changed the pointer update to: p = strchr(p+3, '%') and it worked.
So it had nothing to do with '%' itself, just faulty code.