small change to fread_string()

From: Thomas Arp (t_arp@stofanet.dk)
Date: 04/24/03


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