Welcome to the Builder Academy

Question bug in Alias - specifically dealing with read_aliases_ascii

More
28 Nov 2017 01:36 - 28 Nov 2017 01:55 #7173 by cunning
There are 2 issues as i can see it now. On my live game i have had several players type aliases out. The issue here is that when they exceed 256 characters it now rolls over into the next buffer. I have confirmed it by logging the replacement buffer and watched it leak over into they type buffer.

Nov 27 17:41:00 2017 :: 1) read_aliases: abuf = lvleq - count = 99, i = 0
Nov 27 17:41:00 2017 :: 2) read_aliases: rbuf = get jade orange*get jade orange*rem al*rem al*wear jade*wear jade*get runed orange*get runed orange*wield runed*hold runed* wear hover*get ra orange*get ra orange*rem void*wear ra*wear ra*get cape orange*wear cape*get gloves orange*wear gloves*g
Nov 27 17:41:00 2017 :: 3) read_aliases: tbuf = et rook orange*wear rook


The issue at hand is: rbuf and tbuf from read_aliases_ascii set up the buffers to be 512. However, get_line() only allows 256 characters. We have no check when we create the alias in do_alias() so you can over subscribe the replication buffer. Once it happens, all your aliases now corrupt. I can share with any of the admin if they care to see it.


I had many ideas on how to solve it, but in the end i went with making a new function that allowed up to MAX_INPUT_LENGTH and than added a check in do_alias().
Code:
static void read_aliases_ascii(FILE *file, struct char_data *ch, int count) { int i = 0; if (count == 0) { GET_ALIASES(ch) = NULL; return; /* No aliases in the list. */ } /* This code goes both ways for the old format (where alias and replacement start at the * first character on the line) and the new (where they are prepended by a space in order * to avoid the possibility of a * at the start of the line */ for (i = 0; i < count; i++) { char abuf[MAX_INPUT_LENGTH+1], rbuf[MAX_INPUT_LENGTH+1], tbuf[MAX_INPUT_LENGTH]; /* Read the aliased command. */ get_line(file, abuf); /* Read the replacement. This needs to have a space prepended before placing in * the in-memory struct. The space may be there already, but we can't be certain! */ rbuf[0] = ' '; get_line_long(file, rbuf+1); ====> made a new function /* read the type */ get_line(file, tbuf); if (abuf[0] && rbuf[1] && *tbuf) { struct alias_data *temp; CREATE(temp, struct alias_data, 1); temp->alias = strdup(abuf[0] == ' ' ? abuf+1 : abuf); temp->replacement = strdup(rbuf[1] == ' ' ? rbuf+1 : rbuf); temp->type = atoi(tbuf); temp->next = GET_ALIASES(ch); GET_ALIASES(ch) = temp; } } }
Code:
int get_line_long(FILE *fl, char *buf) { char temp[MAX_INPUT_LENGTH]; int lines = 0; int sl; do { if (!fgets(temp, MAX_INPUT_LENGTH, fl)) return (0); lines++; } while (*temp == '*' || *temp == '\n' || *temp == '\r'); /* Last line of file doesn't always have a \n, but it should. */ sl = strlen(temp); while (sl > 0 && (temp[sl - 1] == '\n' || temp[sl - 1] == '\r')) temp[--sl] = '\0'; strcpy(buf, temp); return (lines); }

In do_alias() I added.
Code:
ACMD(do_alias) ===snippet === if (strlen(repl) >= MAX_INPUT_LENGTH){ send_to_char(ch, "You alias is too long, please revise.\r\n"); return; } CREATE(a, struct alias_data, 1); a->alias = strdup(arg); delete_doubledollar(repl); a->replacement = strdup(repl); if (strchr(repl, ALIAS_SEP_CHAR) || strchr(repl, ALIAS_VAR_CHAR)) a->type = ALIAS_COMPLEX; else a->type = ALIAS_SIMPLE; a->next = GET_ALIASES(ch); GET_ALIASES(ch) = a; save_char(ch); send_to_char(ch, "Alias ready.\r\n");
Last edit: 28 Nov 2017 01:55 by cunning.

Please Log in or Create an account to join the conversation.

Time to create page: 0.475 seconds