From: Jordi Albornoz Date: Sun, 27 Oct 2002 22:31:33 +0000 (+0000) Subject: SECURITY FIXES: replace all uses of strcpy(), strcat(), strncpy() and strncat() with... X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=f9148638c973459bf4b693d0210e026d5d3872d6;p=gtetrinet SECURITY FIXES: replace all uses of strcpy(), strcat(), strncpy() and strncat() with safe versions. Fix buffer overflows in theme code, partyline and other places; cleanup other places to minimize risks. Patch from James Antill. --- diff --git a/ChangeLog b/ChangeLog index d3276f9..6799bca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2002-10-22 James Antill + + * src/tetrinet.c (tetrinet_inmessage): Check all values from atoi() + for out of bounds. + (tetrinet_inmessage): Check all int values from sscanf() for out of + bounds. + (tetrinet_inmessage): Stop buffer overflows in sscanf() %s. + (tetrinet_inmessage): Protect playercount from overflow. + (speclist_add): Protect spectatorcount from overflow. + +2002-10-21 James Antill + + * src/tetrinet.c: Convert hard coded color/attribute values into + constants and %c formats, when used in g_snprintf(). Readability. + + * src/*.c: Replace all uses of sprintf(), strcpy(), strcat(), + strncpy() and strncat() with GTET_STRCPY() or GTET_STRCAT(). + + * src/config.c (config_getthemeinfo): Fixup buffer overflows on theme + info load. + + * src/misc.h (GTET_STRCPY): Added safe strcpy() function. + (GTET_STRCAT): Added safe strcat() function. + (GTET_O_STRCPY): Added safe strcpy() function, with auto size. + (GTET_O_STRCAT): Added safe strcat() function, with auto size. + 2002-10-21 Jordi Mallach * NEWS, configure.in: released gtetrinet 0.4.3. diff --git a/NEWS b/NEWS index fcac8ca..acb6e2d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +GTetrinet 0.4.4 - 2002-10-27 +- SECURITY FIX: multiple buffer overflows fixed all over the place. + This CAN be exploited REMOTELY, please upgrade ASAP. + Special thanks go to Steve Kemp for working on an exploit and its fix, + and James Antill for the patch which fixes the problems in this release. + GTetrinet 0.4.3 - 2002-10-21 - IPv6 support! - Add missing includes so i18n works correctly. diff --git a/src/client.c b/src/client.c index 7ee9276..5fc4049 100644 --- a/src/client.c +++ b/src/client.c @@ -175,8 +175,8 @@ void client_destroypipes (void) void client_init (char *s, char *n) { int i; - strcpy (server, s); - strcpy (nick, n); + GTET_O_STRCPY(server, s); + GTET_O_STRCPY(nick, n); /* wipe spaces off the nick */ for (i = 0; nick[i]; i ++) @@ -236,10 +236,10 @@ static void client_inputfunc (gpointer data, gint source, void client_outmessage (enum outmsg_type msgtype, char *str) { char buf[1024]; - strcpy (buf, outmsg_translate (msgtype)); + GTET_O_STRCPY(buf, outmsg_translate (msgtype)); if (str) { - strcat (buf, " "); - strcat (buf, str); + GTET_O_STRCAT(buf, " "); + GTET_O_STRCAT(buf, str); } write (fdout[1], buf, strlen(buf)); write (fdout[1], "\n", 1); @@ -259,10 +259,10 @@ void client_process (void) if (client_connect () == -1) { char errmsg[1024]; - strcpy (errmsg, "noconnecting "); + GTET_O_STRCPY(errmsg, "noconnecting "); - if (errno) strcat (errmsg, strerror (errno)); - else if (h_errno) strcat (errmsg, "Unknown host"); + if (errno) GTET_O_STRCAT(errmsg, strerror (errno)); + else if (h_errno) GTET_O_STRCAT(errmsg, "Unknown host"); client_inmessage (errmsg); @@ -410,27 +410,43 @@ int client_connect (void) /* say hello to the server */ { - char buf[200], buf2[200]; + GString *s1 = g_string_sized_new(80); + GString *s2 = g_string_sized_new(80); unsigned char ip[4]; - unsigned char iphashbuf[6]; + GString *iphashbuf = g_string_sized_new(11); int i, l, len; + /* construct message */ if (gamemode == TETRIFAST) - sprintf (buf, "tetrifaster %s 1.13", nick); + g_string_sprintf (s1, "tetrifaster %s 1.13", nick); else - sprintf (buf, "tetrisstart %s 1.13", nick); + g_string_sprintf (s1, "tetrisstart %s 1.13", nick); + /* do that encoding thingy */ server_ip (ip); - sprintf (iphashbuf, "%d", ip[0]*54 + ip[1]*41 + ip[2]*29 + ip[3]*17); - l = strlen (iphashbuf); - buf2[0] = 0; - for (i = 0; buf[i]; i ++) - buf2[i+1] = (((buf2[i]&0xFF)+(buf[i]&0xFF))%255) ^ iphashbuf[i%l]; + g_string_sprintf (iphashbuf, "%d", + ip[0]*54 + ip[1]*41 + ip[2]*29 + ip[3]*17); + l = iphashbuf->len; + + g_string_append_c(s2, 0); + for (i = 0; s1->str[i]; i ++) + g_string_append_c(s2, ((((s2->str[i] & 0xFF) + + (s1->str[i] & 0xFF)) % 255) ^ + iphashbuf->str[i % l])); + g_assert(s1->len == i); + g_assert(s2->len == (i + 1)); len = i + 1; + + g_string_truncate(s1, 0); for (i = 0; i < len; i ++) - sprintf (buf+i*2, "%02X", buf2[i] & 0xFF); + g_string_sprintfa(s1, "%02X", s2->str[i] & 0xFF); + /* now send to server */ - client_sendmsg (buf); + client_sendmsg (s1->str); + + g_string_free(s1, TRUE); + g_string_free(s2, TRUE); + g_string_free(iphashbuf, TRUE); } return 0; } diff --git a/src/commands.c b/src/commands.c index b519397..c42fac9 100644 --- a/src/commands.c +++ b/src/commands.c @@ -119,22 +119,22 @@ void detach_command (GtkWidget *widget, gpointer data) void start_command (GtkWidget *widget, gpointer data) { - char buf[16]; - sprintf (buf, "%i %i", 1, playernum); + char buf[22]; + g_snprintf (buf, sizeof(buf), "%i %i", 1, playernum); client_outmessage (OUT_STARTGAME, buf); } void end_command (GtkWidget *widget, gpointer data) { - char buf[16]; - sprintf (buf, "%i %i", 0, playernum); + char buf[22]; + g_snprintf (buf, sizeof(buf), "%i %i", 0, playernum); client_outmessage (OUT_STARTGAME, buf); } void pause_command (GtkWidget *widget, gpointer data) { - char buf[16]; - sprintf (buf, "%i %i", paused?0:1, playernum); + char buf[22]; + g_snprintf (buf, sizeof(buf), "%i %i", paused?0:1, playernum); client_outmessage (OUT_PAUSE, buf); } @@ -207,8 +207,8 @@ void commands_checkstate () if (ingame) partyline_status (_("Game in progress")); else if (connected) { char buf[256]; - strcpy (buf, _("Connected to\n")); - strcat (buf, server); + GTET_O_STRCPY(buf, _("Connected to\n")); + GTET_O_STRCAT(buf, server); partyline_status (buf); } else partyline_status (_("Not connected")); diff --git a/src/config.c b/src/config.c index 248033f..8b67e46 100644 --- a/src/config.c +++ b/src/config.c @@ -32,6 +32,7 @@ #include "client.h" #include "tetrinet.h" #include "sound.h" +#include "misc.h" char blocksfile[1024]; int bsize; @@ -69,9 +70,9 @@ void config_loadtheme (char *themedir) char buf[1024], *p; int i; - strcpy (buf, "="); - strcat (buf, themedir); - strcat (buf, "theme.cfg=/"); + GTET_O_STRCPY(buf, "="); + GTET_O_STRCAT(buf, themedir); + GTET_O_STRCAT(buf, "theme.cfg=/"); gnome_config_push_prefix (buf); @@ -85,15 +86,15 @@ void config_loadtheme (char *themedir) else g_free (p); p = gnome_config_get_string ("Graphics/Blocks=blocks.png"); - strcpy (blocksfile, themedir); - strncat (blocksfile, p, 256); + GTET_O_STRCPY(blocksfile, themedir); + GTET_O_STRCAT(blocksfile, p); g_free (p); bsize = gnome_config_get_int ("Graphics/BlockSize=16"); p = gnome_config_get_string ("Sounds/MidiFile"); if (p) { - strcpy (midifile, themedir); - strncat (midifile, p, 256); + GTET_O_STRCPY(midifile, themedir); + GTET_O_STRCAT(midifile, p); g_free (p); } else @@ -102,8 +103,8 @@ void config_loadtheme (char *themedir) for (i = 0; i < S_NUM; i ++) { p = gnome_config_get_string (soundkeys[i]); if (p) { - strcpy (soundfiles[i], themedir); - strncat (soundfiles[i], p, 256); + GTET_O_STRCPY(soundfiles[i], themedir); + GTET_O_STRCAT(soundfiles[i], p); g_free (p); } else @@ -115,13 +116,14 @@ void config_loadtheme (char *themedir) gnome_config_pop_prefix (); } +/* Arrggh... all these params are sizeof() == 1024 ... this needs a real fix */ int config_getthemeinfo (char *themedir, char *name, char *author, char *desc) { char buf[1024], *p; - strcpy (buf, "="); - strcat (buf, themedir); - strcat (buf, "theme.cfg=/"); + GTET_O_STRCPY (buf, "="); + GTET_O_STRCAT (buf, themedir); + GTET_O_STRCAT (buf, "theme.cfg=/"); gnome_config_push_prefix (buf); @@ -131,17 +133,17 @@ int config_getthemeinfo (char *themedir, char *name, char *author, char *desc) return -1; } else { - if (name) strcpy (name, p); + if (name) GTET_STRCPY(name, p, 1024); g_free (p); } if (author) { p = gnome_config_get_string ("Theme/Author="); - strcpy (author, p); + GTET_STRCPY(author, p, 1024); g_free (p); } if (desc) { p = gnome_config_get_string ("Theme/Description="); - strcpy (desc, p); + GTET_STRCPY(desc, p, 1024); g_free (p); } @@ -158,17 +160,16 @@ void config_loadconfig (void) gnome_config_push_prefix ("/"APPID"/"); p = gnome_config_get_string ("Themes/ThemeDir="DEFAULTTHEME); - strncpy (currenttheme, p, 1024); + GTET_O_STRCPY(currenttheme, p); g_free (p); /* add trailing slash if none exists */ l = strlen(currenttheme); if (currenttheme[l-1] != '/') { - currenttheme[l] = '/'; - currenttheme[l+1] = 0; + GTET_O_STRCAT(currenttheme, "/"); } p = gnome_config_get_string ("Sound/MidiPlayer="DEFAULTMIDICMD); - strncpy (midicmd, p, 1024); + GTET_O_STRCPY(midicmd, p); g_free (p); soundenable = gnome_config_get_int ("Sound/EnableSound=1"); @@ -176,13 +177,13 @@ void config_loadconfig (void) p = gnome_config_get_string ("Player/Nickname"); if (p) { - strncpy (nick, p, 128); + GTET_O_STRCPY(nick, p); g_free(p); } p = gnome_config_get_string ("Player/Team"); if (p) { - strncpy (team, p, 128); + GTET_O_STRCPY(team, p); g_free(p); } diff --git a/src/dialogs.c b/src/dialogs.c index 8ab2168..f38690c 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -163,8 +163,8 @@ void connectdialog_button (GnomeDialog *dialog, gint button, gpointer data) case 0: /* connect now */ spectating = GTK_TOGGLE_BUTTON(spectatorcheck)->active ? TRUE : FALSE; - strcpy (specpassword, gtk_entry_get_text (GTK_ENTRY(passwordentry))); - strcpy (team, gtk_entry_get_text (GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(teamnameentry))))); + GTET_O_STRCPY (specpassword, gtk_entry_get_text (GTK_ENTRY(passwordentry))); + GTET_O_STRCPY (team, gtk_entry_get_text (GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(teamnameentry))))); client_init (gtk_entry_get_text(GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(serveraddressentry)))), gtk_entry_get_text(GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(nicknameentry))))); break; @@ -476,7 +476,8 @@ void prefdialog_changekey (GtkWidget *widget, gpointer data) if (pk_row == -1) return; - sprintf (buf, _("Press new key for \"%s\""), actions[pk_row]); + g_snprintf (buf, sizeof(buf), _("Press new key for \"%s\""), + actions[pk_row]); k = key_dialog (buf); if (k) { newkeys[actionid[pk_row]] = k; @@ -579,11 +580,11 @@ void prefdialog_themelist () int i; char *basedir[2]; - strcpy (dir, getenv ("HOME")); - strcat (dir, "/.gtetrinet/themes"); + GTET_O_STRCPY (dir, getenv ("HOME")); + GTET_O_STRCAT (dir, "/.gtetrinet/themes"); - basedir[0] = GTETRINET_THEMES; - basedir[1] = dir; + basedir[0] = dir; /* load users themes first ... in case we run out */ + basedir[1] = GTETRINET_THEMES; themecount = 0; @@ -591,20 +592,26 @@ void prefdialog_themelist () d = opendir (basedir[i]); if (d) { while ((de = readdir(d))) { - strcpy (buf, basedir[i]); - strcat (buf, "/"); - strcat (buf, de->d_name); - strcat (buf, "/"); + GTET_O_STRCPY (buf, basedir[i]); + GTET_O_STRCAT (buf, "/"); + GTET_O_STRCAT (buf, de->d_name); + GTET_O_STRCAT (buf, "/"); if (config_getthemeinfo(buf, str, NULL, NULL) == 0) { - strcpy (themes[themecount].dir, buf); - strcpy (themes[themecount].name, str); + GTET_O_STRCPY (themes[themecount].dir, buf); + GTET_O_STRCPY (themes[themecount].name, str); themecount ++; + if (themecount == (sizeof(themes) / sizeof(themes[0]))) + { /* FIXME: should be dynamic */ + g_warning("Too many theme files.\n"); + goto too_many_themes; + } } } closedir (d); } } + too_many_themes: qsort (themes, themecount, sizeof(struct themelistentry), themelistcomp); theme_select = 0; @@ -639,7 +646,7 @@ void prefdialog_apply (GnomePropertyBox *dialog, gint pagenum) } if (themechanged) { - strcpy (currenttheme, themes[theme_select].dir); + GTET_O_STRCPY (currenttheme, themes[theme_select].dir); config_loadtheme (currenttheme); fields_page_destroy_contents (); @@ -651,7 +658,7 @@ void prefdialog_apply (GnomePropertyBox *dialog, gint pagenum) if (midichanged) { midi = gtk_entry_get_text (GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(midientry)))); - strcpy (midicmd, midi); + GTET_O_STRCPY (midicmd, midi); } if ((themechanged || midichanged) && ingame) { diff --git a/src/fields.c b/src/fields.c index b5ae5fd..5b38ae8 100644 --- a/src/fields.c +++ b/src/fields.c @@ -388,9 +388,9 @@ void fields_drawblock (int field, int x, int y, char block) void fields_setlabel (int field, char *name, char *team, int num) { - char buf[10]; + char buf[11]; - sprintf (buf, "%d", num); + g_snprintf (buf, sizeof(buf), "%d", num); if (name == NULL) { gtk_widget_hide (fieldlabels[field][0]); @@ -509,7 +509,7 @@ void fields_setlines (int l) { char buf[16] = ""; if (l >= 0) - sprintf (buf, "%d", l); + g_snprintf (buf, sizeof(buf), "%d", l); leftlabel_set (lineswidget, buf); } @@ -517,7 +517,7 @@ void fields_setlevel (int l) { char buf[16] = ""; if (l > 0) - sprintf (buf, "%d", l); + g_snprintf (buf, sizeof(buf), "%d", l); leftlabel_set (levelwidget, buf); } @@ -529,7 +529,7 @@ void fields_setactivelevel (int l) gtk_widget_hide (activewidget); } else { - sprintf (buf, "%d", l); + g_snprintf (buf, sizeof(buf), "%d", l); leftlabel_set (activewidget, buf); gtk_widget_show (activelabel); gtk_widget_show (activewidget); @@ -570,7 +570,7 @@ void fields_gmsginputactivate (int t) if (t) gtk_widget_grab_focus (gmsginput); else - /* do nothing */; + { /* do nothing */; } } void fields_gmsginputadd (char *c) @@ -583,7 +583,7 @@ void fields_gmsginputadd (char *c) void fields_gmsginputback (void) { char buf[256]; - strcpy (buf, gtk_entry_get_text(GTK_ENTRY(gmsginput))); + GTET_O_STRCPY (buf, gtk_entry_get_text(GTK_ENTRY(gmsginput))); if (strlen(buf) == 0) return; buf[strlen(buf)-1] = 0; gtk_entry_set_text (GTK_ENTRY(gmsginput), buf); diff --git a/src/gtetrinet.c b/src/gtetrinet.c index 08ea9f4..1c42a46 100644 --- a/src/gtetrinet.c +++ b/src/gtetrinet.c @@ -74,7 +74,61 @@ static const struct poptOption options[] = { int main (int argc, char *argv[]) { GtkWidget *page, *label, *box; + char buf[1024]; + GTET_STRCPY(buf, "", 4); + g_assert(strlen(buf) == 0); + g_assert(buf[0] == 0); + + GTET_STRCAT(buf, "", 4); + g_assert(strlen(buf) == 0); + g_assert(buf[0] == 0); + + GTET_STRCPY(buf, "a", 1); + g_assert(strlen(buf) == 0); + g_assert(buf[0] == 0); + + GTET_STRCAT(buf, "a", 1); + g_assert(strlen(buf) == 0); + g_assert(buf[0] == 0); + + GTET_STRCPY(buf, "abcd", 4); + g_assert(strlen(buf) == 3); + g_assert(buf[3] == 0); + g_assert(buf[2] == 'c'); + g_assert(buf[1] == 'b'); + g_assert(buf[0] == 'a'); + + GTET_STRCAT(buf, "xyz", 4); + g_assert(strlen(buf) == 3); + g_assert(buf[3] == 0); + g_assert(buf[2] == 'c'); + g_assert(buf[1] == 'b'); + g_assert(buf[0] == 'a'); + + GTET_STRCAT(buf, "abcd", 7); + g_assert(strlen(buf) == 6); + g_assert(buf[6] == 0); + g_assert(buf[5] == 'c'); + g_assert(buf[4] == 'b'); + g_assert(buf[3] == 'a'); + g_assert(buf[2] == 'c'); + g_assert(buf[1] == 'b'); + g_assert(buf[0] == 'a'); + + GTET_O_STRCPY(buf, "abcd"); + GTET_O_STRCAT(buf, "abcd"); + g_assert(strlen(buf) == 8); + g_assert(buf[8] == 0); + g_assert(buf[7] == 'd'); + g_assert(buf[6] == 'c'); + g_assert(buf[5] == 'b'); + g_assert(buf[4] == 'a'); + g_assert(buf[3] == 'd'); + g_assert(buf[2] == 'c'); + g_assert(buf[1] == 'b'); + g_assert(buf[0] == 'a'); + setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); @@ -176,9 +230,9 @@ int main (int argc, char *argv[]) option_connect, option_nick, option_team, option_pass, option_spec); #endif - if (option_nick) strcpy (nick, option_nick); - if (option_team) strcpy (team, option_team); - if (option_pass) strcpy (specpassword, option_pass); + if (option_nick) GTET_O_STRCPY(nick, option_nick); + if (option_team) GTET_O_STRCPY(team, option_team); + if (option_pass) GTET_O_STRCPY(specpassword, option_pass); if (option_spec) spectating = TRUE; if (option_connect) { client_init (option_connect, nick); diff --git a/src/misc.c b/src/misc.c index d611096..9e62fbf 100644 --- a/src/misc.c +++ b/src/misc.c @@ -140,9 +140,9 @@ void textbox_addtext (GtkText *textbox, unsigned char *text) } else if (text[i] < 32) { switch (text[i]) { - case 0x02: attr = attr ^ 0x01; break; /* bold */ - case 0x16: attr = attr ^ 0x02; break; /* italics */ - case 0x1F: break; /* underline not available */ + case TETRI_TB_BOLD: attr = attr ^ 0x01; break; /* bold */ + case TETRI_TB_ITALIC: attr = attr ^ 0x02; break; /* italics */ + case TETRI_TB_UNDERLINE: break; /* underline not available */ default: /* it is a color... */ if (text[i] > 0x1A) goto next; /* bounds checking */ if (text[i] == last) { diff --git a/src/misc.h b/src/misc.h index 7dae59c..d929290 100644 --- a/src/misc.h +++ b/src/misc.h @@ -10,9 +10,56 @@ extern void adjust_bottom (GtkAdjustment *adj); extern char *nocolor (char *str); extern GtkWidget *pixmap_label (GdkPixmap *pm, GdkBitmap *mask, char *str); +/* Better versions of the std. string functions */ +#define GTET_STRCPY(x, y, sz) G_STMT_START { \ + size_t gtet_strcpy_x_sz = (sz); \ + size_t gtet_strcpy_y_len = strlen(y); \ + \ + g_assert(gtet_strcpy_x_sz); \ + \ + if (gtet_strcpy_y_len >= gtet_strcpy_x_sz) \ + gtet_strcpy_y_len = gtet_strcpy_x_sz - 1; \ + \ + if (gtet_strcpy_y_len) \ + memcpy((x), (y), gtet_strcpy_y_len); \ + (x)[gtet_strcpy_y_len] = 0; \ + } G_STMT_END + +#define GTET_STRCAT(x, y, sz) G_STMT_START { \ + size_t gtet_strcat_x_sz = (sz); \ + size_t gtet_strcat_x_len = strlen(x); \ + size_t gtet_strcat_y_len = strlen(y); \ + \ + g_assert(gtet_strcat_x_sz); \ + \ + if (gtet_strcat_x_len >= (gtet_strcat_x_sz - 1)) \ + gtet_strcat_y_len = 0; \ + \ + gtet_strcat_x_sz -= gtet_strcat_x_len; \ + if (gtet_strcat_y_len >= gtet_strcat_x_sz) \ + gtet_strcat_y_len = gtet_strcat_x_sz - 1; \ + \ + if (gtet_strcat_y_len) \ + memcpy((x) + gtet_strcat_x_len, (y), gtet_strcat_y_len); \ + (x)[gtet_strcat_x_len + gtet_strcat_y_len] = 0; \ + } G_STMT_END + +/* these assume you are passing an "object", Ie. sizeof() returns the true + * size */ +#define GTET_O_STRCPY(x, y) G_STMT_START { \ + g_assert(sizeof(x) > 4); GTET_STRCPY(x, y, sizeof(x)); \ + } G_STMT_END + +#define GTET_O_STRCAT(x, y) G_STMT_START { \ + g_assert(sizeof(x) > 4); GTET_STRCAT(x, y, sizeof(x)); \ + } G_STMT_END + /* textbox codes ... */ +#define TETRI_TB_RESET 0xFF + #define TETRI_TB_BOLD 0x2 -#define TETRI_TB_UNDERLINE 0x16 +#define TETRI_TB_ITALIC 0x16 +#define TETRI_TB_UNDERLINE 0x1F /* colors... see colors[] in misc.c */ #define TETRI_TB_C_CYAN 3 diff --git a/src/partyline.c b/src/partyline.c index 6bed189..ddc4930 100644 --- a/src/partyline.c +++ b/src/partyline.c @@ -175,22 +175,24 @@ void partyline_text (char *text) void partyline_playerlist (int *numbers, char **names, char **teams, int n, char **specs, int sn) { int i; - char buf0[16], buf1[128], buf2[128], *item[3] = {buf0, buf1, buf2}; + char buf0[16], buf1[128], buf2[128]; + char *item[3] = {buf0, buf1, buf2}; + /* update the playerlist so that it contains only the given names */ gtk_clist_freeze (GTK_CLIST(playerlist)); gtk_clist_clear (GTK_CLIST(playerlist)); for (i = 0; i < n; i ++) { - sprintf (item[0], "%d", numbers[i]); - strcpy (item[1], nocolor(names[i])); - strcpy (item[2], nocolor(teams[i])); + g_snprintf (buf0, sizeof(buf0), "%d", numbers[i]); + GTET_O_STRCPY (buf1, nocolor(names[i])); + GTET_O_STRCPY (buf2, nocolor(teams[i])); gtk_clist_append (GTK_CLIST(playerlist), item); } buf0[0] = buf1[0] = buf2[0] = 0; gtk_clist_append (GTK_CLIST(playerlist), item); for (i = 0; i < sn; i ++) { - strcpy (item[0], "S"); - strcpy (item[1], nocolor(specs[i])); - strcpy (item[2], ""); + GTET_O_STRCPY (buf0, "S"); + GTET_O_STRCPY (buf1, nocolor(specs[i])); + GTET_O_STRCPY (buf2, ""); gtk_clist_append (GTK_CLIST(playerlist), item); } gtk_clist_thaw (GTK_CLIST(playerlist)); @@ -214,7 +216,7 @@ void textentry (GtkWidget *widget, gpointer data) if (strlen(text) == 0) return; tetrinet_playerline (text); - strcpy (plhistory[plh_end], text); + GTET_O_STRCPY (plhistory[plh_end], text); gtk_entry_set_text (GTK_ENTRY(widget), ""); plh_end ++; @@ -233,7 +235,7 @@ static gint entrykey (GtkWidget *widget, GdkEventKey *key) if (plh_cur == plh_end) { char *text; text = gtk_entry_get_text (GTK_ENTRY(widget)); - strcpy (plhistory[plh_end], text); + GTET_O_STRCPY (plhistory[plh_end], text); } switch (keyval) { case GDK_Up: diff --git a/src/sound.c b/src/sound.c index 32aeb8c..ea327d5 100644 --- a/src/sound.c +++ b/src/sound.c @@ -63,7 +63,6 @@ void sound_playsound (int id) void sound_playmidi (char *file) { #ifdef HAVE_PUTENV - char sz[1024]; #endif sound_stopmidi(); @@ -74,8 +73,11 @@ void sound_playmidi (char *file) #ifdef HAVE_SETENV setenv ("MIDIFILE", file, TRUE); #elif HAVE_PUTENV - sprintf(sz, "MIDIFILE=%s", file); + { + char sz[1024]; + g_snprintf(sz, sizeof(sz), "MIDIFILE=%s", file); putenv(sz); + } #else #error Need either setenv() or putenv() #endif diff --git a/src/tetrinet.c b/src/tetrinet.c index 6ab5fb8..4f730cb 100644 --- a/src/tetrinet.c +++ b/src/tetrinet.c @@ -53,10 +53,12 @@ int playernum = 0; int moderatornum = 0; char team[128], nick[128], specpassword[128]; -char playernames[7][128]; -char teamnames[7][128]; -int playerlevels[7]; -int playerplaying[7]; +#define MAX_PLAYERS 7 + +char playernames[MAX_PLAYERS][128]; +char teamnames[MAX_PLAYERS][128]; +int playerlevels[MAX_PLAYERS]; +int playerplaying[MAX_PLAYERS]; int playercount = 0; char spectatorlist[128][128]; @@ -78,8 +80,16 @@ int gmsgstate; int bigfieldnum; /* game options from the server */ -int initialstackheight, initiallevel, linesperlevel, levelinc, - speciallines, specialcount, specialcapacity, levelaverage, classicmode; +int initialstackheight; /* height of random crap */ +int initiallevel; /* speed speed level */ +int linesperlevel; /* number of lines before you go up a level */ +int levelinc; /* amount you go level up, after every linesperlevel */ +int speciallines; /* ratio of lines needed for special blocks */ +int specialcount; /* multiplier for special blocks to add */ +int specialcapacity; /* max number of specials you can have */ +int levelaverage; /* flag: should we average the levels across all players */ +int classicmode; /* bitflag: does everyone get lines of blocks when you + * 2x, 3x or tetris */ /* these are actually cumulative frequency counts */ int blockfreq[7]; @@ -152,6 +162,7 @@ static FIELD sentfield; /* the field that the server thinks we have */ */ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) { + int tmp_pnum = 0; char buf[1024]; if (msgtype != IN_PLAYERJOIN && msgtype != IN_PLAYERLEAVE && msgtype != IN_TEAM && msgtype != IN_PLAYERNUM && msgtype != IN_CONNECT && msgtype != IN_F && msgtype != IN_WINLIST) { @@ -194,20 +205,23 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) { GtkWidget *dialog; connectingdialog_destroy (); - strcpy (buf, _("Error connecting: ")); - strcat (buf, data); + GTET_O_STRCPY (buf, _("Error connecting: ")); + GTET_O_STRCAT (buf, data); dialog = gnome_message_box_new (buf, GNOME_MESSAGE_BOX_ERROR, GNOME_STOCK_BUTTON_OK, NULL); gtk_widget_show (dialog); } break; case IN_PLAYERNUM: - bigfieldnum = playernum = atoi (data); + tmp_pnum = atoi (data); + if (tmp_pnum >= MAX_PLAYERS) + break; + bigfieldnum = playernum = tmp_pnum; if (!connected) { /* we have successfully connected */ if (spectating) { - sprintf (buf, "%d %s", playernum, specpassword); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, specpassword); client_outmessage (OUT_TEAM, buf); client_outmessage (OUT_VERSION, APPNAME"-"APPVERSION); partyline_namelabel (nick, NULL); @@ -227,10 +241,10 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) } if (!spectating) { /* set own player/team info */ - strcpy (playernames[playernum], nick); - strcpy (teamnames[playernum], team); + GTET_O_STRCPY (playernames[playernum], nick); + GTET_O_STRCPY (teamnames[playernum], team); /* send team info */ - sprintf (buf, "%d %s", playernum, team); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, team); client_outmessage (OUT_TEAM, buf); /* update display */ playerlistupdate (); @@ -251,10 +265,12 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; pnum = atoi (token); + if (pnum >= MAX_PLAYERS) + break; token = strtok (NULL, ""); if (token == NULL) break; if (playernames[pnum][0] == 0) playercount ++; - strcpy (playernames[pnum], token); + GTET_O_STRCPY (playernames[pnum], token); teamnames[pnum][0] = 0; playerlistupdate (); /* update fields display */ @@ -275,6 +291,10 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; pnum = atoi (token); + if (pnum >= MAX_PLAYERS) + break; + if (!playercount) + break; playercount --; if (playernames[pnum][0]) { /* display */ @@ -299,10 +319,18 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; pnum = atoi (token); + if (pnum >= MAX_PLAYERS) + break; if ((pnum == playernum) && !spectating) - sprintf (buf, "\014\02*** You have been kicked from the game"); + g_snprintf (buf, sizeof(buf), + "%c%c*** You have been kicked from the game", + TETRI_TB_C_DARK_GREEN, TETRI_TB_BOLD); else - sprintf (buf, "\014*** \02%s\377\014 has been kicked from the game", playernames[pnum]); + g_snprintf (buf, sizeof(buf), + "%c*** %c%s%c%c has been kicked from the game", + TETRI_TB_C_DARK_GREEN, TETRI_TB_BOLD, + playernames[pnum], + TETRI_TB_RESET, TETRI_TB_C_DARK_GREEN); partyline_text (buf); /* mark it so that leave message is not displayed when playerleave @@ -319,9 +347,11 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; pnum = atoi (token); + if (pnum >= MAX_PLAYERS) + break; token = strtok (NULL, ""); if (token == NULL) token = ""; - strcpy (teamnames[pnum], token); + GTET_O_STRCPY (teamnames[pnum], token); playerlistupdate (); /* update fields display */ fieldslabelupdate (); @@ -336,6 +366,8 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; pnum = atoi (token); + if (pnum >= MAX_PLAYERS) + break; token = strtok (NULL, ""); if (token == NULL) token = ""; if (pnum == 0) { @@ -344,7 +376,7 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) tetrix = TRUE; } else if (tetrix) { - sprintf (buf, "*** %s", token); + g_snprintf (buf, sizeof(buf), "*** %s", token); partyline_text (buf); break; } @@ -360,6 +392,8 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; pnum = atoi (token); + if (pnum >= MAX_PLAYERS) + break; token = strtok (NULL, ""); if (token == NULL) token = ""; /* display it */ @@ -370,6 +404,8 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) { int pnum; pnum = atoi (data); + if (pnum >= MAX_PLAYERS) + break; /* player is out */ playerplaying[pnum] = 0; } @@ -378,12 +414,20 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) { int pnum; pnum = atoi (data); + if (pnum >= MAX_PLAYERS) + break; if (teamnames[pnum][0]) - sprintf (buf, "\020*** Team \02%s\377\020 has won the game", - teamnames[pnum]); + g_snprintf (buf, sizeof(buf), + "%c*** Team %c%s%c%c has won the game", + TETRI_TB_C_DARK_RED, TETRI_TB_BOLD, + teamnames[pnum], + TETRI_TB_RESET, TETRI_TB_C_DARK_RED); else - sprintf (buf, "\020*** \02%s\377\020 has won the game", - playernames[pnum]); + g_snprintf (buf, sizeof(buf), + "%c*** %c%s%c%c has won the game", + TETRI_TB_C_DARK_RED, TETRI_TB_BOLD, + playernames[pnum], + TETRI_TB_RESET, TETRI_TB_C_DARK_RED); partyline_text (buf); } break; @@ -391,11 +435,31 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) { int i, j; char bfreq[128], sfreq[128]; - sscanf (data, "%d %d %d %d %d %d %d %s %s %d %d", + sscanf (data, "%d %d %d %d %d %d %d %128s %128s %d %d", &initialstackheight, &initiallevel, &linesperlevel, &levelinc, &speciallines, &specialcount, &specialcapacity, bfreq, sfreq, &levelaverage, &classicmode); + + bfreq[127] = 0; + sfreq[127] = 0; + + /* initialstackheight == seems ok */ + /* initiallevel == seems ok */ + /* linesperlevel == seems ok */ + /* levelinc == seems ok */ + + if (!speciallines) /* does divide by this number */ + speciallines = 1; + + /* specialcount == seems ok */ + + if ((unsigned int)specialcapacity > sizeof(specialblocks)) + specialcapacity = sizeof(specialblocks); + + /* levelaverage == seems ok */ + /* classicmode == seems ok */ + /* decoding the 11233345666677777 block frequecy thingies: */ @@ -475,6 +539,8 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) s = strtok (data, " "); if (s == NULL) break; pnum = atoi (s); + if (pnum >= MAX_PLAYERS) + break; s = strtok (NULL, ""); if (s == NULL) break; if (*s >= '0') { @@ -488,7 +554,7 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) int block = 0, x, y; for(; *s; s++) { if (*s < '0' && *s >= '!') block = *s - '!'; - else { + else { /* welcome to ASCII hell, x and y tested though */ x = *s - '3'; y = *(++s) - '3'; if (x >= 0 && x < FIELDWIDTH && y >= 0 && y < FIELDHEIGHT) @@ -507,11 +573,15 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; to = atoi (token); + if (to >= MAX_PLAYERS) + break; sbid = strtok (NULL, " "); if (sbid == NULL) break; token = strtok (NULL, ""); if (token == NULL) break; from = atoi(token); + if (from >= MAX_PLAYERS) + break; for (sbnum = 0; sbinfo[sbnum].id; sbnum ++) if (strcmp (sbid, sbinfo[sbnum].id) == 0) break; if (!sbinfo[sbnum].id) break; @@ -525,6 +595,8 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) token = strtok (data, " "); if (token == NULL) break; pnum = atoi (token); + if (pnum >= MAX_PLAYERS) + break; token = strtok (NULL, ""); if (token == NULL) break; playerlevels[pnum] = atoi (token); @@ -564,7 +636,9 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) speclist_clear (); token = strtok (data, " "); if (token == NULL) break; - sprintf (buf, "\021*** You have joined \02%s", token); + g_snprintf (buf, sizeof(buf), + "%c*** You have joined %c%s", + TETRI_TB_C_DARK_BLUE, TETRI_TB_BOLD, token); partyline_text (buf); while ((token = strtok (NULL, " ")) != NULL) speclist_add (token); playerlistupdate (); @@ -578,7 +652,15 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) speclist_add (name); info = strtok (NULL, ""); if (info == NULL) info = ""; - sprintf (buf, "\021*** \02%s\377\021 has joined the spectators \06\02(\02%s\337\06\02)", name, info); + g_snprintf (buf, sizeof(buf), + "%c*** %c%s%c%c has joined the spectators" + " %c%c(%c%s%c%c%c)", + TETRI_TB_C_DARK_BLUE, TETRI_TB_BOLD, + name, + TETRI_TB_RESET, TETRI_TB_C_DARK_BLUE, + TETRI_TB_C_GREY, TETRI_TB_BOLD, TETRI_TB_BOLD, + info, + TETRI_TB_RESET, TETRI_TB_C_GREY, TETRI_TB_BOLD); partyline_text (buf); playerlistupdate (); } @@ -591,7 +673,15 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data) speclist_remove (name); info = strtok (NULL, ""); if (info == NULL) info = ""; - sprintf (buf, "\021*** \02%s\377\021 has left the spectators \06\02(\02%s\337\06\02)", name, info); + g_snprintf (buf, sizeof(buf), + "%c*** %c%s%c%c has left the spectators" + " %c%c(%c%s%c%c%c)", + TETRI_TB_C_DARK_BLUE, TETRI_TB_BOLD, + name, + TETRI_TB_RESET, TETRI_TB_C_DARK_BLUE, + TETRI_TB_C_GREY, TETRI_TB_BOLD, TETRI_TB_BOLD, + info, + TETRI_TB_RESET, TETRI_TB_C_GREY, TETRI_TB_BOLD); partyline_text (buf); playerlistupdate (); } @@ -630,7 +720,7 @@ void tetrinet_playerline (char *text) if (strncasecmp (p, "me ", 3) == 0) { p += 3; while (*p && isspace(*p)) p++; - sprintf (buf, "%d %s", playernum, p); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, p); client_outmessage (OUT_PLINEACT, buf); if (spectating) plinesact (nick, p); @@ -639,12 +729,12 @@ void tetrinet_playerline (char *text) return; } if (tetrix) { - sprintf (buf, "%d %s", playernum, text); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, text); client_outmessage (OUT_PLINE, buf); return; } } - sprintf (buf, "%d %s", playernum, text); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, text); client_outmessage (OUT_PLINE, buf); if (spectating) plinesmsg (nick, text); @@ -656,10 +746,10 @@ void tetrinet_changeteam (char *newteam) { char buf[128]; - strcpy (team, newteam); + GTET_O_STRCPY (team, newteam); if (connected) { - sprintf (buf, "%d %s", playernum, team); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, team); client_outmessage (OUT_TEAM, buf); tetrinet_inmessage (IN_TEAM, buf); partyline_namelabel (nick, team); @@ -673,7 +763,7 @@ void tetrinet_sendfield (int reset) if (reset) goto sendwholefield; - sprintf (buf, "%d ", playernum); + g_snprintf (buf, sizeof(buf), "%d ", playernum); /* find differences between the fields */ for (i = 0; i < 15; i ++) { p = buf2 + 1; @@ -688,7 +778,7 @@ void tetrinet_sendfield (int reset) } if (p > buf2+1) { *p = 0; - strcat (buf, buf2); + GTET_O_STRCAT (buf, buf2); d = TRUE; } } @@ -701,7 +791,7 @@ void tetrinet_sendfield (int reset) for (x = 0; x < FIELDWIDTH; x ++) *p++ = blocks[(int)fields[playernum][y][x]]; *p = 0; - sprintf (buf, "%d %s", playernum, buf2); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, buf2); } /* send it */ client_outmessage (OUT_F, buf); @@ -723,7 +813,7 @@ void tetrinet_resendfield (void) for (x = 0; x < FIELDWIDTH; x ++) *p++ = blocks[(int)sentfield[y][x]]; *p = 0; - sprintf (buf, "%d %s", playernum, buf2); + g_snprintf (buf, sizeof(buf), "%d %s", playernum, buf2); client_outmessage (OUT_F, buf); } @@ -834,19 +924,19 @@ void tetrinet_dospecial (int from, int to, int type) case S_ADDALL4: /* bad for everyone ... */ g_assert(!to); if (from == playernum) - sprintf (buf, "%c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_BLACK, - sbinfo[type].info, - TETRI_TB_C_BLACK, - TETRI_TB_BOLD); + g_snprintf (buf, sizeof(buf), "%c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_BLACK, + sbinfo[type].info, + TETRI_TB_C_BLACK, + TETRI_TB_BOLD); else - sprintf (buf, "%c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_BRIGHT_RED, - sbinfo[type].info, - TETRI_TB_C_BRIGHT_RED, - TETRI_TB_BOLD); + g_snprintf (buf, sizeof(buf), "%c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_BRIGHT_RED, + sbinfo[type].info, + TETRI_TB_C_BRIGHT_RED, + TETRI_TB_BOLD); break; case S_ADDLINE: @@ -855,26 +945,26 @@ void tetrinet_dospecial (int from, int to, int type) case S_BLOCKQUAKE: case S_BLOCKBOMB: /* badish stuff for someone */ if (to == playernum) - sprintf (buf, "%c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_BRIGHT_RED, - sbinfo[type].info, - TETRI_TB_C_BRIGHT_RED, - TETRI_TB_BOLD); + g_snprintf (buf, sizeof(buf), "%c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_BRIGHT_RED, + sbinfo[type].info, + TETRI_TB_C_BRIGHT_RED, + TETRI_TB_BOLD); else if (from == playernum) - sprintf (buf, "%c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_BLACK, - sbinfo[type].info, - TETRI_TB_C_BLACK, - TETRI_TB_BOLD); + g_snprintf (buf, sizeof(buf), "%c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_BLACK, + sbinfo[type].info, + TETRI_TB_C_BLACK, + TETRI_TB_BOLD); else - sprintf (buf, "%c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_DARK_RED, - sbinfo[type].info, - TETRI_TB_C_DARK_RED, - TETRI_TB_BOLD); + g_snprintf (buf, sizeof(buf), "%c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_DARK_RED, + sbinfo[type].info, + TETRI_TB_C_DARK_RED, + TETRI_TB_BOLD); break; case S_CLEARLINE: @@ -882,19 +972,19 @@ void tetrinet_dospecial (int from, int to, int type) case S_SWITCH: case S_GRAVITY: /* goodish stuff for someone */ if (to == playernum) - sprintf (buf, "%c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_BRIGHT_GREEN, - sbinfo[type].info, - TETRI_TB_C_BRIGHT_GREEN, - TETRI_TB_BOLD); + g_snprintf (buf, sizeof(buf), "%c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_BRIGHT_GREEN, + sbinfo[type].info, + TETRI_TB_C_BRIGHT_GREEN, + TETRI_TB_BOLD); else - sprintf (buf, "%c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_DARK_GREEN, - sbinfo[type].info, - TETRI_TB_C_DARK_GREEN, - TETRI_TB_BOLD); + g_snprintf (buf, sizeof(buf), "%c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_DARK_GREEN, + sbinfo[type].info, + TETRI_TB_C_DARK_GREEN, + TETRI_TB_BOLD); break; default: @@ -903,43 +993,43 @@ void tetrinet_dospecial (int from, int to, int type) if (to) { if (to == playernum) - sprintf (buf2, " on %c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_BRIGHT_BLUE, - playernames[to], - TETRI_TB_C_BRIGHT_BLUE, - TETRI_TB_BOLD); + g_snprintf (buf2, sizeof(buf2), " on %c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_BRIGHT_BLUE, + playernames[to], + TETRI_TB_C_BRIGHT_BLUE, + TETRI_TB_BOLD); else - sprintf (buf2, " on %c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_DARK_BLUE, - playernames[to], - TETRI_TB_C_DARK_BLUE, - TETRI_TB_BOLD); - strcat (buf, buf2); + g_snprintf (buf2, sizeof(buf2), " on %c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_DARK_BLUE, + playernames[to], + TETRI_TB_C_DARK_BLUE, + TETRI_TB_BOLD); + GTET_O_STRCAT (buf, buf2); } else { - sprintf (buf2, " to All"); - strcat (buf, buf2); + g_snprintf (buf2, sizeof(buf2), " to All"); + GTET_O_STRCAT (buf, buf2); } if (from) { if (from == playernum) - sprintf (buf2, " by %c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_BRIGHT_BLUE, - playernames[from], - TETRI_TB_C_BRIGHT_BLUE, - TETRI_TB_BOLD); + g_snprintf (buf2, sizeof(buf2), " by %c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_BRIGHT_BLUE, + playernames[from], + TETRI_TB_C_BRIGHT_BLUE, + TETRI_TB_BOLD); else - sprintf (buf2, " by %c%c%s%c%c", - TETRI_TB_BOLD, - TETRI_TB_C_DARK_BLUE, - playernames[from], - TETRI_TB_C_DARK_BLUE, - TETRI_TB_BOLD); - strcat (buf, buf2); + g_snprintf (buf2, sizeof(buf2), " by %c%c%s%c%c", + TETRI_TB_BOLD, + TETRI_TB_C_DARK_BLUE, + playernames[from], + TETRI_TB_C_DARK_BLUE, + TETRI_TB_BOLD); + GTET_O_STRCAT (buf, buf2); } fields_attdefmsg (buf); @@ -1170,7 +1260,7 @@ void tetrinet_resumegame (void) void tetrinet_playerlost (void) { int x, y; - char buf[10]; + char buf[11]; FIELD field; playing = FALSE; /* fix up the display */ @@ -1183,7 +1273,7 @@ void tetrinet_playerlost (void) /* send field */ tetrinet_sendfield (1); /* post message */ - sprintf (buf, "%d", playernum); + g_snprintf (buf, sizeof(buf), "%d", playernum); client_outmessage (OUT_PLAYERLOST, buf); /* make a sound */ sound_playsound (S_YOULOSE); @@ -1348,7 +1438,8 @@ int tetrinet_removelines () llines -= linesperlevel; } /* tell everybody else */ - sprintf (buf, "%d %d", playernum, playerlevels[playernum]); + g_snprintf (buf, sizeof(buf), "%d %d", + playernum, playerlevels[playernum]); client_outmessage (OUT_LVL, buf); tetrinet_updatelevels (); } @@ -1361,7 +1452,8 @@ int tetrinet_removelines () case 4: sbnum = S_ADDALL4; break; default: goto endremovelines; } - sprintf (buf, "%i %s %i", 0, sbinfo[sbnum].id, playernum); + g_snprintf (buf, sizeof(buf), "%i %s %i", + 0, sbinfo[sbnum].id, playernum); client_outmessage (OUT_SB, buf); tetrinet_dospecial (playernum, 0, sbnum); } @@ -1411,12 +1503,12 @@ notfieldkey: if (strlen(s) > 0) { if (strncmp("/me ", s, 4) == 0) { /* post /me thingy */ - sprintf (buf, "* %s %s", nick, s+4); + g_snprintf (buf, sizeof(buf), "* %s %s", nick, s+4); client_outmessage (OUT_GMSG, buf); } else { /* post message */ - sprintf (buf, "<%s> %s", nick, s); + g_snprintf (buf, sizeof(buf), "<%s> %s", nick, s); client_outmessage (OUT_GMSG, buf); } } @@ -1536,7 +1628,7 @@ void tetrinet_specialkey (int pnum) if (pnum == -1) return; /* send it out */ - sprintf (buf, "%i %s %i", pnum, sbinfo[sbnum].id, playernum); + g_snprintf (buf, sizeof(buf), "%i %s %i", pnum, sbinfo[sbnum].id, playernum); client_outmessage (OUT_SB, buf); tetrinet_dospecial (playernum, pnum, sbnum); @@ -1556,7 +1648,11 @@ int moderatorupdate_timeout (void) { if (moderatornum) { char buf[256]; - sprintf (buf, "\024*** \02%s\377\024 is the moderator", playernames[moderatornum]); + g_snprintf (buf, sizeof(buf), + "%c*** %c%s%c%c is the moderator", + TETRI_TB_C_BRIGHT_RED, TETRI_TB_BOLD, + playernames[moderatornum], + TETRI_TB_RESET, TETRI_TB_C_BRIGHT_RED); partyline_text (buf); } mutimeout = 0; @@ -1594,46 +1690,56 @@ int partylineupdate_timeout (void) int f[16]; if (plcount) { - strcpy (buf, "\014*** "); + g_snprintf(buf, sizeof(buf), "%c*** ", TETRI_TB_C_DARK_GREEN); for (i = 0; i < plcount; i++) { - sprintf (buf2, "\02%s\377\014, ", pleaves[i]); - strcat (buf, buf2); + g_snprintf (buf2, sizeof(buf2), "%c%s%c%c, ", + TETRI_TB_BOLD, pleaves[i], + TETRI_TB_RESET, TETRI_TB_C_DARK_GREEN); + GTET_O_STRCAT (buf, buf2); } - buf[strlen(buf)-2] = 0; - if (plcount == 1) strcat (buf, _(" has left the game")); - else strcat (buf, _(" have left the game")); + buf[strlen(buf)-2] = 0; /* remove ", " from end of string */ + if (plcount == 1) GTET_O_STRCAT (buf, _(" has left the game")); + else GTET_O_STRCAT (buf, _(" have left the game")); plcount = 0; partyline_text (buf); } if (pcount) { - strcpy (buf, "\014*** "); + g_snprintf(buf, sizeof(buf), "%c*** ", TETRI_TB_C_DARK_GREEN); for (i = 0; i < pcount; i++) { - sprintf (buf2, "\02%s\377\014, ", pjoins[i]); - strcat (buf, buf2); + g_snprintf (buf2, sizeof(buf2), "%c%s%c%c, ", + TETRI_TB_BOLD, pjoins[i], + TETRI_TB_RESET, TETRI_TB_C_DARK_GREEN); + GTET_O_STRCAT (buf, buf2); } buf[strlen(buf)-2] = 0; - if (pcount == 1) strcat (buf, _(" has joined the game")); - else strcat (buf, _(" have joined the game")); + if (pcount == 1) GTET_O_STRCAT (buf, _(" has joined the game")); + else GTET_O_STRCAT (buf, _(" have joined the game")); partyline_text (buf); for (i = 0; i < pcount; i ++) f[i] = 1; for (i = 0; i < pcount; i ++) if (f[i]) { - strcpy (team, pteams[i]); - sprintf (buf, "\020*** \02%s\377\020", pjoins[i]); + GTET_O_STRCPY (team, pteams[i]); + g_snprintf (buf, sizeof(buf), "%c*** %c%s%c%c", + TETRI_TB_C_DARK_RED, TETRI_TB_BOLD, + pjoins[i], + TETRI_TB_RESET, TETRI_TB_C_DARK_RED); c = 1; for (j = i+1; j < pcount; j ++) { if (strcmp (team, pteams[j]) == 0) { - sprintf (buf2, ", \02%s\377\020", pjoins[j]); - strcat (buf, buf2); + g_snprintf (buf2, sizeof(buf2), ", %c%s%c%c", + TETRI_TB_BOLD, pjoins[j], + TETRI_TB_RESET, TETRI_TB_C_DARK_RED); + GTET_O_STRCAT (buf, buf2); f[j] = 0; c ++; } } - if (c == 1) strcat (buf, " is "); - else strcat (buf, " are "); - if (team[0]) sprintf (buf2, "on team \02%s", team); - else sprintf (buf2, "alone"); - strcat (buf, buf2); + if (c == 1) GTET_O_STRCAT (buf, " is "); + else GTET_O_STRCAT (buf, " are "); + if (team[0]) g_snprintf (buf2, sizeof(buf2), "on team %c%s", + TETRI_TB_BOLD, team); + else g_snprintf (buf2, sizeof(buf2), "alone"); + GTET_O_STRCAT (buf, buf2); partyline_text (buf); } pcount = 0; @@ -1658,7 +1764,7 @@ void partylineupdate_join (char *name) int i; if (!connected) return; for (i = 0; i < pcount; i ++) if (strcmp(pjoins[i], name) == 0) return; - strcpy (pjoins[pcount], name); + GTET_O_STRCPY (pjoins[pcount], name); pteams[pcount][0] = 0; pcount ++; partylineupdate (0); @@ -1674,21 +1780,28 @@ void partylineupdate_team (char *name, char *team) char buf[1024]; /* player did not just join - display normally */ if (team[0]) - sprintf (buf, "\020*** \02%s\377\020 is now on team \02%s", - name, team); + g_snprintf (buf, sizeof(buf), + "%c*** %c%s%c%c is now on team %c%s", + TETRI_TB_C_DARK_RED, TETRI_TB_BOLD, + name, + TETRI_TB_RESET, TETRI_TB_C_DARK_RED, + TETRI_TB_BOLD, team); else - sprintf (buf, "\020*** \02%s\377\020 is now alone", - name); + g_snprintf (buf, sizeof(buf), + "%c*** %c%s%c%c is now alone", + TETRI_TB_C_DARK_RED, TETRI_TB_BOLD, + name, + TETRI_TB_RESET, TETRI_TB_C_DARK_RED); partyline_text (buf); } - strcpy (pteams[i], team); + GTET_O_STRCPY (pteams[i], team); partylineupdate (0); } void partylineupdate_leave (char *name) { if (!connected) return; - strcpy (pleaves[plcount], name); + GTET_O_STRCPY (pleaves[plcount], name); plcount ++; partylineupdate (0); } @@ -1740,28 +1853,39 @@ void checkmoderatorstatus (void) void plinemsg (char *name, char *text) { char buf[1024]; - sprintf (buf, "\02<%s\377\02>\02 %s", name, text); + g_snprintf (buf, sizeof(buf), "%c<%s%c%c>%c %s", + TETRI_TB_BOLD, name, + TETRI_TB_RESET, TETRI_TB_BOLD, TETRI_TB_BOLD, text); partyline_text (buf); } void plinesmsg (char *name, char *text) { char buf[1024]; - sprintf (buf, "\05\02<%s\377\05\02>\02 %s", name, text); + g_snprintf (buf, sizeof(buf), "%c%c<%s%c%c%c>%c %s", + TETRI_TB_C_BRIGHT_BLUE, TETRI_TB_BOLD, + name, + TETRI_TB_RESET, + TETRI_TB_C_BRIGHT_BLUE, TETRI_TB_BOLD, TETRI_TB_BOLD, text); partyline_text (buf); } void plineact (char *name, char *text) { char buf[1024]; - sprintf (buf, "\023* \02%s\377\023 %s", name, text); + g_snprintf (buf, sizeof(buf), "%c* %c%s%c%c %s", + TETRI_TB_C_PURPLE, TETRI_TB_BOLD, name, + TETRI_TB_RESET, TETRI_TB_C_PURPLE, text); partyline_text (buf); } void plinesact (char *name, char *text) { char buf[1024]; - sprintf (buf, "\05* \02%s\377\05 %s", name, text); + g_snprintf (buf, sizeof(buf), "%c* %c%s%c%c %s", + TETRI_TB_C_BRIGHT_BLUE, TETRI_TB_BOLD, + name, + TETRI_TB_RESET, TETRI_TB_C_BRIGHT_BLUE, text); partyline_text (buf); } @@ -1796,11 +1920,15 @@ void speclist_clear (void) void speclist_add (char *name) { int p, i; + + if (spectatorcount == (sizeof(spectatorlist) / sizeof(spectatorlist[0]))) + return; + for (p = 0; p < spectatorcount; p++) if (strcasecmp(name, spectatorlist[p]) < 0) break; for (i = spectatorcount; i > p; i--) - strcpy (spectatorlist[i], spectatorlist[i-1]); - strcpy (spectatorlist[p], name); + GTET_O_STRCPY (spectatorlist[i], spectatorlist[i-1]); + GTET_O_STRCPY (spectatorlist[p], name); spectatorcount ++; } @@ -1810,7 +1938,7 @@ void speclist_remove (char *name) for (i = 0; i < spectatorcount; i ++) { if (strcmp(name, spectatorlist[i]) == 0) { for (; i < spectatorcount-1; i++) - strcpy (spectatorlist[i], spectatorlist[i+1]); + GTET_O_STRCPY (spectatorlist[i], spectatorlist[i+1]); spectatorcount --; return; } diff --git a/src/winlist.c b/src/winlist.c index 16e8c16..708918c 100644 --- a/src/winlist.c +++ b/src/winlist.c @@ -69,7 +69,7 @@ void winlist_additem (int team, char *name, int score) if (team) item[0] = "T"; else item[0] = ""; item[1] = nocolor (name); - sprintf (buf, "%d", score); + g_snprintf (buf, sizeof(buf), "%d", score); item[2] = buf; gtk_clist_append (GTK_CLIST(winlist), item);