From b061066838c74d533a77e405a53a57059c5f68f6 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 17 Jul 1998 21:47:07 +0000 Subject: Strictly check whether catalog file is larger enough for the data. --- catgets/open_catalog.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'catgets/open_catalog.c') diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c index 9d54124..deaa871 100644 --- a/catgets/open_catalog.c +++ b/catgets/open_catalog.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,10 @@ __open_catalog (__nl_catd catalog) int fd = -1; struct stat st; int swapping; + size_t cnt; + size_t max_offset; + size_t tab_size; + const char *lastp; /* Make sure we are alone. */ __libc_lock_lock (catalog->lock); @@ -175,11 +180,19 @@ __open_catalog (__nl_catd catalog) } /* Avoid dealing with directories and block devices */ - if (fd < 0 || __fstat (fd, &st) < 0 || !S_ISREG (st.st_mode)) + if (fd < 0 || __fstat (fd, &st) < 0) { catalog->status = nonexisting; goto unlock_return; } + if (!S_ISREG (st.st_mode) || st.st_size < sizeof (struct catalog_obj)) + { + /* `errno' is not set correctly but the file is not usable. + Use an reasonable error value. */ + __set_errno (EINVAL); + catalog->status = nonexisting; + goto unlock_return; + } #ifndef MAP_COPY /* Linux seems to lack read-only copy-on-write. */ @@ -242,6 +255,7 @@ __open_catalog (__nl_catd catalog) swapping = 1; else { + invalid_file: /* Invalid file. Free the resources and mark catalog as not usable. */ if (catalog->status == mmapped) @@ -276,6 +290,29 @@ __open_catalog (__nl_catd catalog) (const char *) &catalog->file_ptr->name_ptr[catalog->plane_size * catalog->plane_depth * 3 * 2]; + /* Determine the largest string offset mentioned in the table. */ + max_offset = 0; + tab_size = 3 * catalog->plane_size * catalog->plane_depth; + for (cnt = 2; cnt < tab_size; cnt += 3) + if (catalog->name_ptr[cnt] > max_offset) + max_offset = catalog->name_ptr[cnt]; + + /* Now we can check whether the file is large enough to contain the + tables it says it contains. */ + if (st.st_size <= (sizeof (struct catalog_obj) + 2 * tab_size + max_offset)) + /* The last string is not contained in the file. */ + goto invalid_file; + + lastp = catalog->strings + max_offset; + max_offset = (st.st_size + - sizeof (struct catalog_obj) + 2 * tab_size + max_offset); + while (*lastp != '\0') + { + if (--max_offset == 0) + goto invalid_file; + ++lastp; + } + /* Release the lock again. */ unlock_return: if (fd != -1) -- cgit v1.1