2002-03-27 20:57:06 +00:00
|
|
|
/* update-game-score.c --- Update a score file
|
2008-05-09 23:19:13 +00:00
|
|
|
|
2023-01-01 10:31:12 +00:00
|
|
|
Copyright (C) 2002-2023 Free Software Foundation, Inc.
|
2008-05-09 23:19:13 +00:00
|
|
|
|
|
|
|
Author: Colin Walters <walters@debian.org>
|
2002-03-27 20:57:06 +00:00
|
|
|
|
|
|
|
This file is part of GNU Emacs.
|
|
|
|
|
2008-05-09 23:19:13 +00:00
|
|
|
GNU Emacs is free software: you can redistribute it and/or modify
|
2002-03-27 20:57:06 +00:00
|
|
|
it under the terms of the GNU General Public License as published by
|
2016-03-10 15:34:52 +00:00
|
|
|
the Free Software Foundation, either version 3 of the License, or (at
|
|
|
|
your option) any later version.
|
2002-03-27 20:57:06 +00:00
|
|
|
|
|
|
|
GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2017-09-13 22:52:52 +00:00
|
|
|
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
2008-05-09 23:19:13 +00:00
|
|
|
|
2002-03-27 20:57:06 +00:00
|
|
|
|
2009-09-24 01:44:35 +00:00
|
|
|
/* This program allows a game to securely and atomically update a
|
2015-01-16 08:25:25 +00:00
|
|
|
score file. It should be installed either setuid or setgid, owned
|
|
|
|
by an appropriate user or group like `games'.
|
2002-04-10 19:10:23 +00:00
|
|
|
|
|
|
|
Alternatively, it can be compiled without HAVE_SHARED_GAME_DIR
|
|
|
|
defined, and in that case it will store scores in the user's home
|
|
|
|
directory (it should NOT be setuid).
|
2002-03-27 20:57:06 +00:00
|
|
|
|
2008-05-09 23:19:13 +00:00
|
|
|
Created 2002/03/22.
|
2002-03-27 20:57:06 +00:00
|
|
|
*/
|
|
|
|
|
2002-04-16 20:05:08 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2002-03-27 20:57:06 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
#include <inttypes.h>
|
2011-08-28 23:59:14 +00:00
|
|
|
#include <limits.h>
|
2002-03-27 20:57:06 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
2002-04-05 08:58:12 +00:00
|
|
|
#include <pwd.h>
|
2002-03-27 20:57:06 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
2012-04-16 00:41:01 +00:00
|
|
|
#include <getopt.h>
|
2002-11-18 15:35:07 +00:00
|
|
|
|
Use unlocked stdio more systematically
This can improve performance significantly on stdio-bottlenecked code.
E.g., make-docfile is 3x faster on my Fedora 25 x86-64 desktop.
* admin/merge-gnulib (GNULIB_MODULES): Add unlocked-io.
* lib-src/ebrowse.c, lib-src/emacsclient.c, lib-src/etags.c:
* lib-src/hexl.c, lib-src/make-docfile.c, lib-src/movemail.c:
* lib-src/profile.c, lib-src/update-game-score.c:
Include unlocked-io.h instead of stdio.h, since these programs are
single-threaded.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lib/unlocked-io.h, m4/unlocked-io.m4: New files, copied from Gnulib.
* src/charset.c, src/cm.c, src/emacs.c, src/image.c, src/keyboard.c:
* src/lread.c, src/term.c:
Include sysstdio.h, possibly instead of stdio.h, to define
the unlocked functions if the system does not provide them.
* src/charset.c, src/lread.c (getc_unlocked):
Remove, since sysstdio.h now defines it if needed.
* src/cm.c (cmputc, cmcheckmagic):
* src/dispnew.c (update_frame, update_frame_with_menu)
(update_frame_1, Fsend_string_to_terminal, Fding, bitch_at_user):
* src/emacs.c (main, Fdump_emacs):
* src/fileio.c (Fdo_auto_save, Fset_binary_mode):
* src/image.c (slurp_file, png_read_from_file, png_load_body)
(our_stdio_fill_input_buffer):
* src/keyboard.c (record_char, kbd_buffer_get_event, handle_interrupt):
* src/lread.c (readbyte_from_file):
* src/minibuf.c (read_minibuf_noninteractive):
* src/print.c (printchar_to_stream, strout)
(Fredirect_debugging_output):
* src/sysdep.c (reset_sys_modes, procfs_ttyname)
(procfs_get_total_memory):
* src/term.c (tty_ring_bell, tty_send_additional_strings)
(tty_set_terminal_modes, tty_reset_terminal_modes)
(tty_update_end, tty_clear_end_of_line, tty_write_glyphs)
(tty_write_glyphs_with_face, tty_insert_glyphs)
(tty_menu_activate):
* src/xfaces.c (Fx_load_color_file):
Use unlocked stdio when it should be safe.
* src/sysstdio.h (clearerr_unlocked, feof_unlocked, ferror_unlocked)
(fflush_unlocked, fgets_unlocked, fputc_unlocked, fputs_unlocked)
(fread_unlocked, fwrite_unlocked, getc_unlocked, getchar_unlocked)
(putc_unlocked, putchar_unloced): Provide substitutes if not declared.
2017-06-22 18:21:20 +00:00
|
|
|
#include <unlocked-io.h>
|
|
|
|
|
2013-03-30 17:00:51 +00:00
|
|
|
#ifdef WINDOWSNT
|
|
|
|
#include "ntlib.h"
|
|
|
|
#endif
|
|
|
|
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
#ifndef min
|
|
|
|
# define min(a,b) ((a) < (b) ? (a) : (b))
|
|
|
|
#endif
|
|
|
|
|
2002-03-27 20:57:06 +00:00
|
|
|
#define MAX_ATTEMPTS 5
|
2002-04-10 19:10:23 +00:00
|
|
|
#define MAX_DATA_LEN 1024
|
2002-04-07 05:46:15 +00:00
|
|
|
|
2012-06-24 17:39:14 +00:00
|
|
|
static _Noreturn void
|
2010-07-03 00:50:23 +00:00
|
|
|
usage (int err)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2011-07-09 10:32:42 +00:00
|
|
|
fprintf (stdout, "Usage: update-game-score [-m MAX] [-r] [-d DIR] game/scorefile SCORE DATA\n");
|
2003-02-04 12:00:09 +00:00
|
|
|
fprintf (stdout, " update-game-score -h\n");
|
|
|
|
fprintf (stdout, " -h\t\tDisplay this help.\n");
|
|
|
|
fprintf (stdout, " -m MAX\t\tLimit the maximum number of scores to MAX.\n");
|
|
|
|
fprintf (stdout, " -r\t\tSort the scores in increasing order.\n");
|
|
|
|
fprintf (stdout, " -d DIR\t\tStore scores in DIR (only if not setuid).\n");
|
|
|
|
exit (err);
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int lock_file (const char *filename, void **state);
|
|
|
|
static int unlock_file (const char *filename, void *state);
|
2002-03-27 20:57:06 +00:00
|
|
|
|
|
|
|
struct score_entry
|
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
char *score;
|
|
|
|
char *user_data;
|
2002-03-27 20:57:06 +00:00
|
|
|
};
|
|
|
|
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
#define MAX_SCORES min (PTRDIFF_MAX, SIZE_MAX / sizeof (struct score_entry))
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int read_scores (const char *filename, struct score_entry **scores,
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
ptrdiff_t *count, ptrdiff_t *alloc);
|
|
|
|
static int push_score (struct score_entry **scores, ptrdiff_t *count,
|
|
|
|
ptrdiff_t *size, struct score_entry const *newscore);
|
|
|
|
static void sort_scores (struct score_entry *scores, ptrdiff_t count,
|
|
|
|
bool reverse);
|
2015-01-16 08:25:25 +00:00
|
|
|
static int write_scores (const char *filename, mode_t mode,
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
const struct score_entry *scores, ptrdiff_t count);
|
2002-08-01 01:31:44 +00:00
|
|
|
|
2012-06-24 17:39:14 +00:00
|
|
|
static _Noreturn void
|
2010-07-03 00:50:23 +00:00
|
|
|
lose (const char *msg)
|
2002-08-01 01:31:44 +00:00
|
|
|
{
|
2003-02-04 12:00:09 +00:00
|
|
|
fprintf (stderr, "%s\n", msg);
|
2004-05-08 15:26:33 +00:00
|
|
|
exit (EXIT_FAILURE);
|
2002-08-01 01:31:44 +00:00
|
|
|
}
|
2002-03-27 20:57:06 +00:00
|
|
|
|
2012-06-24 17:39:14 +00:00
|
|
|
static _Noreturn void
|
2010-07-03 00:50:23 +00:00
|
|
|
lose_syserr (const char *msg)
|
2002-04-29 22:49:00 +00:00
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
fprintf (stderr, "%s: %s\n", msg,
|
|
|
|
errno ? strerror (errno) : "Invalid data in score file");
|
2004-05-08 15:26:33 +00:00
|
|
|
exit (EXIT_FAILURE);
|
2002-04-29 22:49:00 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static char *
|
2010-07-02 12:19:53 +00:00
|
|
|
get_user_id (void)
|
2002-04-05 08:58:12 +00:00
|
|
|
{
|
2003-02-04 12:00:09 +00:00
|
|
|
struct passwd *buf = getpwuid (getuid ());
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
if (!buf || strchr (buf->pw_name, ' ') || strchr (buf->pw_name, '\n'))
|
2002-04-05 08:58:12 +00:00
|
|
|
{
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
intmax_t uid = getuid ();
|
|
|
|
char *name = malloc (sizeof uid * CHAR_BIT / 3 + 4);
|
2011-08-28 23:59:14 +00:00
|
|
|
if (name)
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
sprintf (name, "%"PRIdMAX, uid);
|
2002-04-05 08:58:12 +00:00
|
|
|
return name;
|
|
|
|
}
|
|
|
|
return buf->pw_name;
|
|
|
|
}
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static const char *
|
2015-01-16 08:25:25 +00:00
|
|
|
get_prefix (bool privileged, const char *user_prefix)
|
2002-04-10 19:10:23 +00:00
|
|
|
{
|
2015-01-16 08:25:25 +00:00
|
|
|
if (privileged)
|
2002-04-29 22:49:00 +00:00
|
|
|
{
|
|
|
|
#ifdef HAVE_SHARED_GAME_DIR
|
|
|
|
return HAVE_SHARED_GAME_DIR;
|
|
|
|
#else
|
2015-01-16 08:25:25 +00:00
|
|
|
lose ("This program was compiled without HAVE_SHARED_GAME_DIR,\n"
|
|
|
|
"and should not run with elevated privileges.");
|
2002-04-29 22:49:00 +00:00
|
|
|
#endif
|
|
|
|
}
|
2015-01-16 08:25:25 +00:00
|
|
|
if (user_prefix == NULL)
|
|
|
|
lose ("Not using a shared game directory, and no prefix given.");
|
2002-04-29 22:49:00 +00:00
|
|
|
return user_prefix;
|
2002-04-10 19:10:23 +00:00
|
|
|
}
|
|
|
|
|
2014-05-19 04:56:03 +00:00
|
|
|
static char *
|
|
|
|
normalize_integer (char *num)
|
|
|
|
{
|
|
|
|
bool neg;
|
|
|
|
char *p;
|
|
|
|
while (*num != '\n' && isspace (*num))
|
|
|
|
num++;
|
|
|
|
neg = *num == '-';
|
|
|
|
num += neg || *num == '-';
|
|
|
|
|
|
|
|
if (*num == '0')
|
|
|
|
{
|
|
|
|
while (*++num == '0')
|
|
|
|
continue;
|
|
|
|
neg &= !!*num;
|
|
|
|
num -= !*num;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (p = num; '0' <= *p && *p <= '9'; p++)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (*p || p == num)
|
|
|
|
{
|
|
|
|
errno = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (neg)
|
|
|
|
*--num = '-';
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
2002-03-27 20:57:06 +00:00
|
|
|
int
|
2010-07-03 00:50:23 +00:00
|
|
|
main (int argc, char **argv)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
int c;
|
2015-01-16 08:25:25 +00:00
|
|
|
bool running_suid, running_sgid;
|
2002-03-27 20:57:06 +00:00
|
|
|
void *lockstate;
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
char *scorefile;
|
2014-05-19 04:56:03 +00:00
|
|
|
char *end, *nl, *user, *data;
|
Fix warnings produced by compiling with -Wwrite_strings (i.e. use const char *).
* b2m.c (concat, fatal): Use const char*.
(main): Don't assign labels a string literal.
* ebrowse.c (struct member): filename, def_filename is const.
(struct sym): filename, sfilename is const.
(struct kw): name is const.
(add_sym, yyerror, token_string, insert_keyword, main): Use const char*.
* emacsclient.c (message, sock_err_message, send_to_emacs)
(quote_argument, set_local_socket)
(start_daemon_and_retry_set_socket): Use const char*.
* etags.c (compressor, language, Ada_suffix, Ada_help, Asm_suffixes)
(Asm_help, default_C_suffixes, default_C_help, Cplusplus_suffixes)
(Cplusplus_help, Cjava_suffixes, Cobol_suffixes, Cstar_suffixes)
(Erlang_suffixes, Erlang_help, Forth_suffixes, Forth_help)
(Fortran_suffixes, Fortran_help, HTML_suffixes, HTML_help)
(Lisp_suffixes, Lisp_help, Lua_suffixes, Lua_help)
(Makefile_filenames, Makefile_help, Objc_suffixes, Objc_help)
(Pascal_suffixes, Pascal_help, Perl_suffixes, Perl_interpreters)
(Perl_help, PHP_suffixes, PHP_help, plain_C_suffixses, PS_suffixes)
(PS_help, Prolog_suffixes, Prolog_help, Python_suffixes, Python_help)
(Scheme_suffixes, Scheme_help, TeX_suffixes, TeX_help, Texinfo_suffixes)
(Texinfo_help, Yacc_suffixes, Yacc_help, auto_help, none_help)
(no_lang_help, print_language_names)
(get_language_from_interpreter, get_language_from_filename)
(init, make_tag, struct C_stab_entry, write_classname, TEX_defenv)
(TEX_decode_env, nocase_tail, savestr, savenstr, fatal, pfatal)
(concat): Use const char*.
* make-docfile.c (error, fatal, scan_c_file, scan_lisp_file): Use
const char *.
* movemail.c (fatal, error, concat): Use const char *.
* pop.c (pop_multi_first, socket_connection, sendline): Use conat char*.
* pop.h (pop_multi_first): Use const char *.
(_ARGS): Remove.
* sorted-doc.c (error, fatal, states): Use const char *.
* update-game-score.c (get_prefix, write_scores, main): Use const char*.
2010-08-11 08:20:34 +00:00
|
|
|
const char *prefix, *user_prefix = NULL;
|
2002-03-27 20:57:06 +00:00
|
|
|
struct score_entry *scores;
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
struct score_entry newscore;
|
|
|
|
bool reverse = false;
|
|
|
|
ptrdiff_t scorecount, scorealloc;
|
|
|
|
ptrdiff_t max_scores = MAX_SCORES;
|
2002-03-27 20:57:06 +00:00
|
|
|
|
2003-02-04 12:00:09 +00:00
|
|
|
while ((c = getopt (argc, argv, "hrm:d:")) != -1)
|
2002-03-27 20:57:06 +00:00
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case 'h':
|
2004-05-08 15:26:33 +00:00
|
|
|
usage (EXIT_SUCCESS);
|
2002-03-27 20:57:06 +00:00
|
|
|
break;
|
2002-04-29 22:49:00 +00:00
|
|
|
case 'd':
|
|
|
|
user_prefix = optarg;
|
|
|
|
break;
|
2002-03-27 20:57:06 +00:00
|
|
|
case 'r':
|
|
|
|
reverse = 1;
|
|
|
|
break;
|
|
|
|
case 'm':
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
intmax_t m = strtoimax (optarg, &end, 10);
|
|
|
|
if (optarg == end || *end || m < 0)
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
usage (EXIT_FAILURE);
|
|
|
|
max_scores = min (m, MAX_SCORES);
|
|
|
|
}
|
2002-03-27 20:57:06 +00:00
|
|
|
break;
|
|
|
|
default:
|
2004-05-08 15:26:33 +00:00
|
|
|
usage (EXIT_FAILURE);
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
if (argc - optind != 3)
|
2004-05-08 15:26:33 +00:00
|
|
|
usage (EXIT_FAILURE);
|
2002-04-07 05:46:15 +00:00
|
|
|
|
2003-02-04 12:00:09 +00:00
|
|
|
running_suid = (getuid () != geteuid ());
|
2015-01-16 08:25:25 +00:00
|
|
|
running_sgid = (getgid () != getegid ());
|
|
|
|
if (running_suid && running_sgid)
|
|
|
|
lose ("This program can run either suid or sgid, but not both.");
|
2002-04-07 05:46:15 +00:00
|
|
|
|
2015-01-16 08:25:25 +00:00
|
|
|
prefix = get_prefix (running_suid || running_sgid, user_prefix);
|
2002-04-10 19:10:23 +00:00
|
|
|
|
2003-02-04 12:00:09 +00:00
|
|
|
scorefile = malloc (strlen (prefix) + strlen (argv[optind]) + 2);
|
2002-03-27 20:57:06 +00:00
|
|
|
if (!scorefile)
|
2003-02-04 12:00:09 +00:00
|
|
|
lose_syserr ("Couldn't allocate score file");
|
2002-04-10 19:10:23 +00:00
|
|
|
|
Prefer stpcpy to strcat
* admin/merge-gnulib (GNULIB_MODULES): Add stpcpy.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* lib/stpcpy.c, m4/stpcpy.m4: New files, from gnulib.
* lib-src/ebrowse.c (sym_scope_1, operator_name, open_file):
* lib-src/emacsclient.c (get_server_config, set_local_socket)
(start_daemon_and_retry_set_socket):
* lib-src/etags.c (main, C_entries, relative_filename):
* lib-src/pop.c (sendline):
* lib-src/update-game-score.c (main):
* lwlib/xlwmenu.c (resource_widget_value):
* src/callproc.c (child_setup):
* src/dbusbind.c (xd_signature_cat):
* src/doc.c (get_doc_string, Fsnarf_documentation):
* src/editfns.c (Fuser_full_name):
* src/frame.c (xrdb_get_resource):
* src/gtkutil.c (xg_get_file_with_chooser):
* src/tparam.c (tparam1):
* src/xfns.c (xic_create_fontsetname):
* src/xrdb.c (gethomedir, get_user_db, get_environ_db):
* src/xsmfns.c (smc_save_yourself_CB):
Rewrite to avoid the need for strcat, typically by using stpcpy
and/or lispstpcpy. strcat tends to be part of O(N**2) algorithms.
* src/doc.c (sibling_etc):
* src/xrdb.c (xdefaults):
Now a top-level static constant.
2014-12-25 12:19:17 +00:00
|
|
|
char *z = stpcpy (scorefile, prefix);
|
|
|
|
*z++ = '/';
|
|
|
|
strcpy (z, argv[optind]);
|
2002-04-29 22:49:00 +00:00
|
|
|
|
2014-05-19 04:56:03 +00:00
|
|
|
newscore.score = normalize_integer (argv[optind + 1]);
|
|
|
|
if (! newscore.score)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "%s: Invalid score\n", argv[optind + 1]);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
|
2014-05-19 04:56:03 +00:00
|
|
|
user = get_user_id ();
|
|
|
|
if (! user)
|
|
|
|
lose_syserr ("Couldn't determine user id");
|
|
|
|
data = argv[optind + 2];
|
Avoid some strlen work, primarily via strnlen
* admin/merge-gnulib (GNULIB_MODULES): Add strnlen.
* lib-src/etags.c (find_entries):
* src/emacs.c (main):
* src/nsmenu.m (parseKeyEquiv:):
* src/nsterm.m (ns_xlfd_to_fontname):
* src/term.c (vfatal):
Prefer !*X to !strlen (X).
* lib-src/etags.c (pfnote, add_regex):
* lib-src/pop.c (pop_open):
* lib-src/update-game-score.c (main):
* lwlib/lwlib.c (lw_separator_p):
* src/doprnt.c (doprnt):
* src/emacs.c (main):
* src/inotify.c (inotifyevent_to_event):
* src/keyboard.c (menu_separator_name_p, parse_tool_bar_item):
* src/sysdep.c (get_current_dir_name_or_unreachable):
* src/xdisp.c (store_mode_line_string):
Use strnlen to avoid unnecessary work with strlen.
* lib-src/etags.c (Prolog_functions, prolog_pr)
(Erlang_functions, erlang_func):
Prefer ptrdiff_t to size_t when either will do.
(prolog_pr, erlang_func): New arg LASTLEN, to avoid
unnecessary strlen call. All callers changed.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lib/strnlen.c, m4/strnlen.m4: New files, copied from Gnulib.
* lwlib/lwlib.c (lw_separator_p):
* src/json.c (json_has_prefix):
Use strncmp to avoid unecessary work with strlen + memcmp.
* src/process.c (set_socket_option): Use SBYTES instead of strlen.
2019-06-25 21:53:39 +00:00
|
|
|
if (strnlen (data, MAX_DATA_LEN + 1) == MAX_DATA_LEN + 1)
|
2014-05-19 04:56:03 +00:00
|
|
|
data[MAX_DATA_LEN] = '\0';
|
|
|
|
nl = strchr (data, '\n');
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
if (nl)
|
|
|
|
*nl = '\0';
|
2014-05-19 04:56:03 +00:00
|
|
|
newscore.user_data = malloc (strlen (user) + 1 + strlen (data) + 1);
|
|
|
|
if (! newscore.user_data
|
|
|
|
|| sprintf (newscore.user_data, "%s %s", user, data) < 0)
|
|
|
|
lose_syserr ("Memory exhausted");
|
2003-02-04 14:56:31 +00:00
|
|
|
|
2003-02-04 12:00:09 +00:00
|
|
|
if (lock_file (scorefile, &lockstate) < 0)
|
|
|
|
lose_syserr ("Failed to lock scores file");
|
2003-02-04 14:56:31 +00:00
|
|
|
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
if (read_scores (scorefile, &scores, &scorecount, &scorealloc) < 0)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2003-02-04 12:00:09 +00:00
|
|
|
unlock_file (scorefile, lockstate);
|
|
|
|
lose_syserr ("Failed to read scores file");
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
if (push_score (&scores, &scorecount, &scorealloc, &newscore) < 0)
|
|
|
|
{
|
|
|
|
unlock_file (scorefile, lockstate);
|
|
|
|
lose_syserr ("Failed to add score");
|
|
|
|
}
|
2009-09-11 19:11:07 +00:00
|
|
|
sort_scores (scores, scorecount, reverse);
|
2002-04-10 19:10:23 +00:00
|
|
|
/* Limit the number of scores. If we're using reverse sorting, then
|
2011-03-21 07:46:53 +00:00
|
|
|
also increment the beginning of the array, to skip over the
|
|
|
|
*smallest* scores. Otherwise, just decrementing the number of
|
|
|
|
scores suffices, since the smallest is at the end. */
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
if (scorecount > max_scores)
|
2011-03-21 07:46:53 +00:00
|
|
|
{
|
|
|
|
if (reverse)
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
scores += scorecount - max_scores;
|
|
|
|
scorecount = max_scores;
|
2011-03-21 07:46:53 +00:00
|
|
|
}
|
2015-01-16 08:25:25 +00:00
|
|
|
if (write_scores (scorefile, running_sgid ? 0664 : 0644,
|
|
|
|
scores, scorecount) < 0)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2003-02-04 12:00:09 +00:00
|
|
|
unlock_file (scorefile, lockstate);
|
|
|
|
lose_syserr ("Failed to write scores file");
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
if (unlock_file (scorefile, lockstate) < 0)
|
|
|
|
lose_syserr ("Failed to unlock scores file");
|
2004-05-08 15:26:33 +00:00
|
|
|
exit (EXIT_SUCCESS);
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
2014-05-19 04:56:03 +00:00
|
|
|
static char *
|
|
|
|
read_score (char *p, struct score_entry *score)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
score->score = p;
|
|
|
|
p = strchr (p, ' ');
|
|
|
|
if (!p)
|
|
|
|
return p;
|
|
|
|
*p++ = 0;
|
|
|
|
score->user_data = p;
|
|
|
|
p = strchr (p, '\n');
|
|
|
|
if (!p)
|
|
|
|
return p;
|
|
|
|
*p++ = 0;
|
|
|
|
return p;
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
read_scores (const char *filename, struct score_entry **scores,
|
|
|
|
ptrdiff_t *count, ptrdiff_t *alloc)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
char *p, *filedata;
|
|
|
|
ptrdiff_t filesize, nread;
|
|
|
|
struct stat st;
|
2003-02-04 12:00:09 +00:00
|
|
|
FILE *f = fopen (filename, "r");
|
2003-02-04 14:56:31 +00:00
|
|
|
if (!f)
|
2002-03-27 20:57:06 +00:00
|
|
|
return -1;
|
2014-05-19 04:56:03 +00:00
|
|
|
if (fstat (fileno (f), &st) != 0)
|
|
|
|
return -1;
|
|
|
|
if (! (0 <= st.st_size && st.st_size < min (PTRDIFF_MAX, SIZE_MAX)))
|
|
|
|
{
|
|
|
|
errno = EOVERFLOW;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
filesize = st.st_size;
|
|
|
|
filedata = malloc (filesize + 1);
|
|
|
|
if (! filedata)
|
|
|
|
return -1;
|
|
|
|
nread = fread (filedata, 1, filesize + 1, f);
|
|
|
|
if (filesize < nread)
|
|
|
|
{
|
|
|
|
errno = 0;
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
return -1;
|
2014-05-19 04:56:03 +00:00
|
|
|
}
|
|
|
|
if (nread < filesize)
|
|
|
|
filesize = nread;
|
|
|
|
if (ferror (f) || fclose (f) != 0)
|
|
|
|
return -1;
|
|
|
|
filedata[filesize] = 0;
|
|
|
|
if (strlen (filedata) != filesize)
|
2013-08-05 17:09:28 +00:00
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
errno = 0;
|
|
|
|
return -1;
|
2013-08-05 17:09:28 +00:00
|
|
|
}
|
2014-05-19 04:56:03 +00:00
|
|
|
|
|
|
|
*scores = 0;
|
|
|
|
*count = *alloc = 0;
|
|
|
|
for (p = filedata; p < filedata + filesize; )
|
|
|
|
{
|
|
|
|
struct score_entry entry;
|
|
|
|
p = read_score (p, &entry);
|
|
|
|
if (!p)
|
|
|
|
{
|
|
|
|
errno = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (push_score (scores, count, alloc, &entry) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int
|
2010-07-03 00:50:23 +00:00
|
|
|
score_compare (const void *a, const void *b)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
|
|
|
const struct score_entry *sa = (const struct score_entry *) a;
|
|
|
|
const struct score_entry *sb = (const struct score_entry *) b;
|
2014-05-19 04:56:03 +00:00
|
|
|
char *sca = sa->score;
|
|
|
|
char *scb = sb->score;
|
|
|
|
size_t lena, lenb;
|
|
|
|
bool nega = *sca == '-';
|
|
|
|
bool negb = *scb == '-';
|
|
|
|
int diff = nega - negb;
|
|
|
|
if (diff)
|
|
|
|
return diff;
|
|
|
|
if (nega)
|
|
|
|
{
|
|
|
|
char *tmp = sca;
|
|
|
|
sca = scb + 1;
|
|
|
|
scb = tmp + 1;
|
|
|
|
}
|
|
|
|
lena = strlen (sca);
|
|
|
|
lenb = strlen (scb);
|
|
|
|
if (lena != lenb)
|
|
|
|
return lenb < lena ? -1 : 1;
|
|
|
|
return strcmp (scb, sca);
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int
|
2010-07-03 00:50:23 +00:00
|
|
|
score_compare_reverse (const void *a, const void *b)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
return score_compare (b, a);
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
push_score (struct score_entry **scores, ptrdiff_t *count, ptrdiff_t *size,
|
|
|
|
struct score_entry const *newscore)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
struct score_entry *newscores = *scores;
|
|
|
|
if (*count == *size)
|
|
|
|
{
|
|
|
|
ptrdiff_t newsize = *size;
|
|
|
|
if (newsize <= 0)
|
|
|
|
newsize = 1;
|
|
|
|
else if (newsize <= MAX_SCORES / 2)
|
|
|
|
newsize *= 2;
|
|
|
|
else if (newsize < MAX_SCORES)
|
|
|
|
newsize = MAX_SCORES;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
errno = ENOMEM;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
newscores = realloc (newscores, sizeof *newscores * newsize);
|
|
|
|
if (!newscores)
|
|
|
|
return -1;
|
|
|
|
*scores = newscores;
|
|
|
|
*size = newsize;
|
|
|
|
}
|
|
|
|
newscores[*count] = *newscore;
|
2002-03-27 20:57:06 +00:00
|
|
|
(*count) += 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static void
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
sort_scores (struct score_entry *scores, ptrdiff_t count, bool reverse)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
qsort (scores, count, sizeof *scores,
|
|
|
|
reverse ? score_compare_reverse : score_compare);
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int
|
2015-01-16 08:25:25 +00:00
|
|
|
write_scores (const char *filename, mode_t mode,
|
|
|
|
const struct score_entry *scores, ptrdiff_t count)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2013-08-04 16:56:56 +00:00
|
|
|
int fd;
|
2003-02-04 14:56:31 +00:00
|
|
|
FILE *f;
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
ptrdiff_t i;
|
2003-02-04 12:00:09 +00:00
|
|
|
char *tempfile = malloc (strlen (filename) + strlen (".tempXXXXXX") + 1);
|
2002-03-27 20:57:06 +00:00
|
|
|
if (!tempfile)
|
|
|
|
return -1;
|
Prefer stpcpy to strcat
* admin/merge-gnulib (GNULIB_MODULES): Add stpcpy.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* lib/stpcpy.c, m4/stpcpy.m4: New files, from gnulib.
* lib-src/ebrowse.c (sym_scope_1, operator_name, open_file):
* lib-src/emacsclient.c (get_server_config, set_local_socket)
(start_daemon_and_retry_set_socket):
* lib-src/etags.c (main, C_entries, relative_filename):
* lib-src/pop.c (sendline):
* lib-src/update-game-score.c (main):
* lwlib/xlwmenu.c (resource_widget_value):
* src/callproc.c (child_setup):
* src/dbusbind.c (xd_signature_cat):
* src/doc.c (get_doc_string, Fsnarf_documentation):
* src/editfns.c (Fuser_full_name):
* src/frame.c (xrdb_get_resource):
* src/gtkutil.c (xg_get_file_with_chooser):
* src/tparam.c (tparam1):
* src/xfns.c (xic_create_fontsetname):
* src/xrdb.c (gethomedir, get_user_db, get_environ_db):
* src/xsmfns.c (smc_save_yourself_CB):
Rewrite to avoid the need for strcat, typically by using stpcpy
and/or lispstpcpy. strcat tends to be part of O(N**2) algorithms.
* src/doc.c (sibling_etc):
* src/xrdb.c (xdefaults):
Now a top-level static constant.
2014-12-25 12:19:17 +00:00
|
|
|
strcpy (stpcpy (tempfile, filename), ".tempXXXXXX");
|
2013-08-04 16:56:56 +00:00
|
|
|
fd = mkostemp (tempfile, 0);
|
|
|
|
if (fd < 0)
|
|
|
|
return -1;
|
Fix the MSDOS build.
src/unexcoff.c [MSDOS]: Include libc/atexit.h.
(copy_text_and_data): Zero out the atexit chain pointer before
dumping Emacs.
src/termhooks.h (encode_terminal_code): Update prototype.
src/term.c (encode_terminal_code) [DOS_NT]: Make it externally
visible for all DOS_NT ports, not just WINDOWSNT.
(syms_of_term) [!MSDOS]: Don't define 'tty-menu-*' symbols on MSDOS.
src/sysdep.c (emacs_sigaction_init, init_signals): Don't use SIGCHLD
unless it is defined.
(emacs_pipe) [MSDOS]: Redirect to 'pipe'.
src/process.c (close_on_exec, accept4, process_socket): Move into
the "ifdef subprocesses" part.
(catch_child_signal): Condition by "ifdef subprocesses".
(syms_of_process) <Qinternal_default_process_sentinel>
<Qinternal_default_process_filter>: Condition by "ifdef subprocesses".
src/msdos.h: Add prototypes for new functions.
(EINPROGRESS): Define.
(O_CLOEXEC): Define to zero.
src/msdos.c (check_window_system): Remove unnecessary an
incompatible duplicate function.
(sys_opendir, readlinkat, faccessat, fstatat, unsetenv): New
functions in support of new functionality.
src/menu.c (single_menu_item): Add visual indication of submenu
also for menus on MSDOS frames.
(Fx_popup_menu) [!MSDOS]: Do not call tty_menu_show on MSDOS.
src/lisp.h (CHECK_PROCESS) [!subprocesses]: Do not define
when async subprocesses aren't supported.
src/font.h (FONT_WIDTH) [MSDOS]: MSDOS-specific definition.
src/emacs.c (close_output_streams): Zero out errno before calling
close_stream.
src/dired.c [MSDOS]: Include msdos.h.
src/conf_post.h (opendir) [MSDOS]: Redirect to sys_opendir.
(DATA_START) [MSDOS]: Define.
(SYSTEM_PURESIZE_EXTRA) [MSDOS]: Enlarge by 25K.
src/callproc.c (block_child_signal, unblock_child_signal) [MSDOS]:
Ifdef away for MSDOS.
(record_kill_process) [MSDOS]: Ifdef away the entire body for MSDOS.
(call_process_cleanup) [MSDOS]: Ifdef away portions not relevant
for MSDOS.
(call_process) [MSDOS]: Fix call sequence of dostounix_filename.
Use temporary file template that is compatible with mkostemp.
Move vfork-related portions under #ifndef MSDOS.
(syms_of_callproc): Unify templates of MSDOS and WINDOWSNT.
lisp/term/pc-win.el (x-list-fonts, x-get-selection-value): Provide
doc strings, as required by snarf-documentation.
msdos/sedlisp.inp:
msdos/sedlibmk.inp:
msdos/sedleim.inp:
msdos/sed3v2.inp:
msdos/sed2v2.inp:
msdos/sed1v2.inp: Update Sed scripts for Emacs 24.4.
msdos/inttypes.h: Add PRIdMAX.
msdos/INSTALL: Update for Emacs 24.4.
msdos/sedadmin.inp: New file.
2014-04-16 13:27:28 +00:00
|
|
|
#ifndef DOS_NT
|
2015-01-16 08:25:25 +00:00
|
|
|
if (fchmod (fd, mode) != 0)
|
2014-01-22 19:02:41 +00:00
|
|
|
return -1;
|
2014-01-22 19:38:31 +00:00
|
|
|
#endif
|
2013-08-04 16:56:56 +00:00
|
|
|
f = fdopen (fd, "w");
|
|
|
|
if (! f)
|
2002-03-27 20:57:06 +00:00
|
|
|
return -1;
|
|
|
|
for (i = 0; i < count; i++)
|
2014-05-19 04:56:03 +00:00
|
|
|
if (fprintf (f, "%s %s\n", scores[i].score, scores[i].user_data) < 0)
|
2002-03-27 20:57:06 +00:00
|
|
|
return -1;
|
2014-01-22 19:02:41 +00:00
|
|
|
if (fclose (f) != 0)
|
2002-03-27 20:57:06 +00:00
|
|
|
return -1;
|
2014-01-22 19:02:41 +00:00
|
|
|
if (rename (tempfile, filename) != 0)
|
2002-03-27 20:57:06 +00:00
|
|
|
return -1;
|
2002-04-10 19:10:23 +00:00
|
|
|
return 0;
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int
|
2010-07-03 00:50:23 +00:00
|
|
|
lock_file (const char *filename, void **state)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
|
|
|
int fd;
|
2002-04-14 06:40:19 +00:00
|
|
|
struct stat buf;
|
2002-03-27 20:57:06 +00:00
|
|
|
int attempts = 0;
|
Fix warnings produced by compiling with -Wwrite_strings (i.e. use const char *).
* b2m.c (concat, fatal): Use const char*.
(main): Don't assign labels a string literal.
* ebrowse.c (struct member): filename, def_filename is const.
(struct sym): filename, sfilename is const.
(struct kw): name is const.
(add_sym, yyerror, token_string, insert_keyword, main): Use const char*.
* emacsclient.c (message, sock_err_message, send_to_emacs)
(quote_argument, set_local_socket)
(start_daemon_and_retry_set_socket): Use const char*.
* etags.c (compressor, language, Ada_suffix, Ada_help, Asm_suffixes)
(Asm_help, default_C_suffixes, default_C_help, Cplusplus_suffixes)
(Cplusplus_help, Cjava_suffixes, Cobol_suffixes, Cstar_suffixes)
(Erlang_suffixes, Erlang_help, Forth_suffixes, Forth_help)
(Fortran_suffixes, Fortran_help, HTML_suffixes, HTML_help)
(Lisp_suffixes, Lisp_help, Lua_suffixes, Lua_help)
(Makefile_filenames, Makefile_help, Objc_suffixes, Objc_help)
(Pascal_suffixes, Pascal_help, Perl_suffixes, Perl_interpreters)
(Perl_help, PHP_suffixes, PHP_help, plain_C_suffixses, PS_suffixes)
(PS_help, Prolog_suffixes, Prolog_help, Python_suffixes, Python_help)
(Scheme_suffixes, Scheme_help, TeX_suffixes, TeX_help, Texinfo_suffixes)
(Texinfo_help, Yacc_suffixes, Yacc_help, auto_help, none_help)
(no_lang_help, print_language_names)
(get_language_from_interpreter, get_language_from_filename)
(init, make_tag, struct C_stab_entry, write_classname, TEX_defenv)
(TEX_decode_env, nocase_tail, savestr, savenstr, fatal, pfatal)
(concat): Use const char*.
* make-docfile.c (error, fatal, scan_c_file, scan_lisp_file): Use
const char *.
* movemail.c (fatal, error, concat): Use const char *.
* pop.c (pop_multi_first, socket_connection, sendline): Use conat char*.
* pop.h (pop_multi_first): Use const char *.
(_ARGS): Remove.
* sorted-doc.c (error, fatal, states): Use const char *.
* update-game-score.c (get_prefix, write_scores, main): Use const char*.
2010-08-11 08:20:34 +00:00
|
|
|
const char *lockext = ".lockfile";
|
2003-02-04 12:00:09 +00:00
|
|
|
char *lockpath = malloc (strlen (filename) + strlen (lockext) + 60);
|
2002-03-27 20:57:06 +00:00
|
|
|
if (!lockpath)
|
|
|
|
return -1;
|
Prefer stpcpy to strcat
* admin/merge-gnulib (GNULIB_MODULES): Add stpcpy.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* lib/stpcpy.c, m4/stpcpy.m4: New files, from gnulib.
* lib-src/ebrowse.c (sym_scope_1, operator_name, open_file):
* lib-src/emacsclient.c (get_server_config, set_local_socket)
(start_daemon_and_retry_set_socket):
* lib-src/etags.c (main, C_entries, relative_filename):
* lib-src/pop.c (sendline):
* lib-src/update-game-score.c (main):
* lwlib/xlwmenu.c (resource_widget_value):
* src/callproc.c (child_setup):
* src/dbusbind.c (xd_signature_cat):
* src/doc.c (get_doc_string, Fsnarf_documentation):
* src/editfns.c (Fuser_full_name):
* src/frame.c (xrdb_get_resource):
* src/gtkutil.c (xg_get_file_with_chooser):
* src/tparam.c (tparam1):
* src/xfns.c (xic_create_fontsetname):
* src/xrdb.c (gethomedir, get_user_db, get_environ_db):
* src/xsmfns.c (smc_save_yourself_CB):
Rewrite to avoid the need for strcat, typically by using stpcpy
and/or lispstpcpy. strcat tends to be part of O(N**2) algorithms.
* src/doc.c (sibling_etc):
* src/xrdb.c (xdefaults):
Now a top-level static constant.
2014-12-25 12:19:17 +00:00
|
|
|
strcpy (stpcpy (lockpath, filename), lockext);
|
2002-03-27 20:57:06 +00:00
|
|
|
*state = lockpath;
|
2014-05-19 04:56:03 +00:00
|
|
|
|
|
|
|
while ((fd = open (lockpath, O_CREAT | O_EXCL, 0600)) < 0)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
if (errno != EEXIST)
|
|
|
|
return -1;
|
|
|
|
attempts++;
|
|
|
|
|
|
|
|
/* Break the lock if it is over an hour old, or if we've tried
|
|
|
|
more than MAX_ATTEMPTS times. We won't corrupt the file, but
|
|
|
|
we might lose some scores. */
|
|
|
|
if (MAX_ATTEMPTS < attempts
|
|
|
|
|| (stat (lockpath, &buf) == 0 && 60 * 60 < time (0) - buf.st_ctime))
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
2014-05-19 04:56:03 +00:00
|
|
|
if (unlink (lockpath) != 0 && errno != ENOENT)
|
|
|
|
return -1;
|
|
|
|
attempts = 0;
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
2023-03-21 21:38:23 +00:00
|
|
|
else
|
|
|
|
sleep (1);
|
2002-03-27 20:57:06 +00:00
|
|
|
}
|
2014-05-19 04:56:03 +00:00
|
|
|
|
2003-02-04 12:00:09 +00:00
|
|
|
close (fd);
|
2002-03-27 20:57:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
2011-02-21 18:06:25 +00:00
|
|
|
static int
|
2010-07-03 00:50:23 +00:00
|
|
|
unlock_file (const char *filename, void *state)
|
2002-03-27 20:57:06 +00:00
|
|
|
{
|
|
|
|
char *lockpath = (char *) state;
|
|
|
|
int saved_errno = errno;
|
update-game-score fixes for -m and integer overflow
* update-game-score.c: Include inttypes.h, stdbool.h.
(min): New macro, if not already defined.
(MAX_SCORES, main): Limit the maximum number of scores only from
limits imposed by the underyling platform, instead of the
arbitrary value 200.
(struct score_entry, main, read_score, write_score):
Scores are now intmax_t, not long.
(get_user_id): Reject user names containing spaces or newlines,
as they would mess up the score file.
Allow uids that don't fit in 'long'.
Increase the size of the buffer, to avoid overrun in weird cases.
(get_prefix, main): Use bool for boolean.
(main): Rewrite expr to avoid possibility of signed integer
overflow. Don't allow newlines in data, as this would mess up
the score file. Check for memory allocation failure when adding
the new score, or when unlockint the file. Implement -m.
(read_score): Check for integer overflow when reading a score.
(read_score) [!HAVE_GETDELIM]: Check for integer overflow when
data gets very long. Check only for space to delimit names,
since that's what's done in the HAVE_GETDELIM case.
(read_scores): New parameter ALLOC. Change counts to ptrdiff_t.
All uses changed. Use push_score to add individual scores;
that's simpler than repeating its contents.
(score_compare_reverse): Simplify.
(push_score): New parameter SIZE. Change counts to ptrdiff_t.
All uses changed. Check for integer overflow of size calculation.
(sort_scores, write_scores): Change counts to ptrdiff_t.
(unlock_file): Preserve errno on success, so that storage
exhaustion is diagnosed correctly.
Fixes: debbugs:16428
2014-01-19 08:50:53 +00:00
|
|
|
int ret = unlink (lockpath);
|
2020-12-25 09:38:31 +00:00
|
|
|
if (0 <= ret)
|
|
|
|
errno = saved_errno;
|
2003-02-04 12:00:09 +00:00
|
|
|
free (lockpath);
|
2002-03-27 20:57:06 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2003-09-01 15:45:59 +00:00
|
|
|
|
2004-05-08 15:26:33 +00:00
|
|
|
/* update-game-score.c ends here */
|