I've been irritated for a long time by the mud refusing to boot after a reboot/crash, due to ~'s in the world files. These tildes have snuck past smash_tilde(), and I have to admit, it have bugged me that we had to have such a strict policy regarding their use, that we've completely banned the use. So I set forth to make a change in fread_string, the function that chokes on ~'s in the wrong places. The change makes fread_string terminate reading correctly when a ~ is ending a line. If it's in the middle or beginning, it continues reading. A subtle bug is that if a builder puts a ~on the end of a line, they still make the port unbootable. To prevent this, I've changed the smash_tilde function, and made sure that all text altering functions are smash_tilde'd before saving by having genolc_check_string() call smash_tilde instead of disallowing ~'s completely. Also, the change fixes an issue with fread_string and dos/windows files, as line\r\n line number 2\r\n were previously translated to "line\r\r\nline number 2\r\r\n" and not the correct "line\r\nline number 2\r\n" And to sum it all up, it fixes a potential overrun on tmp. db.c: /* read and allocate space for a '~'-terminated string from a given file */ char *fread_string(FILE *fl, const char *error) { - char buf[MAX_STRING_LENGTH], tmp[512]; + char buf[MAX_STRING_LENGTH], tmp[514]; char *point; int done = 0, length = 0, templength; *buf = '\0'; do { if (!fgets(tmp, 512, fl)) { log("SYSERR: fread_string: format error at or near %s", error); exit(1); } /* If there is a '~', end the string; else put an "\r\n" over the '\n'. */ - if ((point = strchr(tmp, '~')) != NULL) { - *point = '\0'; - done = 1; - } else { - point = tmp + strlen(tmp) - 1; - *(point++) = '\r'; - *(point++) = '\n'; - *point = '\0'; - } + /* Fix by Welcor: + * If the ~ isn't at the end of the string, keep reading. + */ + /* Assumption: the fgets() call above will always contain at least 2 chars */ + /* namely '\n' and '\0'. "point--" then makes sense.*/ + point = strchr(tmp, '\0'); + for (point-- ; (*point=='\r' || *point=='\n'); point--); + if (*point=='~') { + *point='\0'; + done = 1; + } else { + *(++point) = '\r'; + *(++point) = '\n'; + *(++point) = '\0'; + } templength = point - tmp; if (length + templength >= MAX_STRING_LENGTH) { log("SYSERR: fread_string: string too large (db.c)"); log("%s", error); exit(1); } else { strcat(buf + length, tmp); /* strcat: OK (size checked above) */ length += templength; } } while (!done); /* allocate space for the new string and copy it */ return (strlen(buf) ? strdup(buf) : NULL); } modify.c: void smash_tilde(char *str) { /* * Erase any _line ending_ tildes inserted in the editor. * The load mechanism can't handle those, yet. * -- Welcor 04/2003 */ char *p = str; for (; *p; p++) if (*p == '~' && (*(p+1)=='\r' || *(p+1)=='\n' || *(p+1)=='\0')) *p=' '; } Welcor -- +---------------------------------------------------------------+ | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html | | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html | | Newbie List: http://groups.yahoo.com/group/circle-newbies/ | +---------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 06/26/03 PDT