diff options
author | celest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-02-01 11:57:21 +0000 |
---|---|---|
committer | celest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-02-01 11:57:21 +0000 |
commit | ac349965467725bf4b9690994733cc2b6694cdd4 (patch) | |
tree | de14d4a0824739e76c0f7e5acd320b59414be521 | |
parent | d90b9f6768e9e33efc97d769f24fe0315da683ac (diff) | |
download | hercules-ac349965467725bf4b9690994733cc2b6694cdd4.tar.gz hercules-ac349965467725bf4b9690994733cc2b6694cdd4.tar.bz2 hercules-ac349965467725bf4b9690994733cc2b6694cdd4.tar.xz hercules-ac349965467725bf4b9690994733cc2b6694cdd4.zip |
* Fixed an overflow in grfio
* Changed resnametable loading behaviour
* Increased grfio filelist limit to 1048576
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5152 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r-- | Changelog-Trunk.txt | 6 | ||||
-rw-r--r-- | src/common/grfio.c | 299 | ||||
-rw-r--r-- | src/common/grfio.h | 7 |
3 files changed, 89 insertions, 223 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 7e9ed73a6..ca9108106 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,12 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. EVERYTHING ELSE
GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS
+2006/02/01
+ * Fixed an overflow in grfio causing read problems in Win32 builds [celest]
+ * Changed resnametable loading behaviour - grfio will load from data directory
+ first, and then from the highest priority grf only if that fails [celest]
+ * Increased grfio filelist limit to 1048576 to avoid problems when loading
+ too many large grfs [celest]
2006/01/31
* Fixed skill_check_cloak to use the current skill level of the cloaking
skill and not pc_checkskill() to know if a cloaker away from a wall should
diff --git a/src/common/grfio.c b/src/common/grfio.c index a3907a7f2..eef4ea654 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -61,7 +61,7 @@ typedef struct { int declen; // original size
int srcpos;
short next;
- char cycle;
+ int cycle;
char type;
char fn[128-4*5]; // file name
char gentry; // read grf file select
@@ -75,7 +75,7 @@ typedef struct { //Since char defines *FILELIST.gentry, the maximum which can be added by grfio_add becomes by 127 pieces.
#define GENTRY_LIMIT 127
-#define FILELIST_LIMIT 65536 // temporary maximum, and a theory top maximum are 2G.
+#define FILELIST_LIMIT 1048576 // temporary maximum, and a theory top maximum are 2G.
static FILELIST *filelist = NULL;
static int filelist_entrys = 0;
@@ -85,17 +85,6 @@ static char **gentry_table = NULL; static int gentry_entrys = 0;
static int gentry_maxentry = 0;
-#define RESNAME_LIMIT 1024
-#define RESNAME_ADDS 16
-
-typedef struct resname_entry {
- char src[64];
- char dst[64];
-} Resname;
-static struct resname_entry *localresname = NULL;
-static int resname_entrys = 0;
-static int resname_maxentrys = 0;
-
//----------------------------
// file list hash table
//----------------------------
@@ -333,78 +322,6 @@ int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* return err;
}
-/*==========================================
-* Decompress from file source to file dest until stream ends or EOF.
-* inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
-* allocated for processing, Z_DATA_ERROR if the deflate data is
-* invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
-* the version of the library linked do not match, or Z_ERRNO if there
-* is an error reading or writing the files.
-*
-* Version 1.2 9 November 2004 Mark Adler
-*------------------------------------------
-*/
-int decode_file (FILE *source, FILE *dest)
-{
- int err;
- unsigned have;
- z_stream strm;
- unsigned char in[CHUNK];
- unsigned char out[CHUNK];
-
- /* allocate inflate state */
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = 0;
- strm.next_in = Z_NULL;
-
- err = inflateInit(&strm);
- if (err != Z_OK) return 0; //return err;
-
- /* decompress until deflate stream ends or end of file */
- do {
- strm.avail_in = fread(in, 1, CHUNK, source);
- if (ferror(source)) {
- inflateEnd(&strm);
- return 0;
- }
- if (strm.avail_in == 0)
- break;
- strm.next_in = in;
-
- /* run inflate() on input until output buffer not full */
- do {
- strm.avail_out = CHUNK;
- strm.next_out = out;
- err = inflate(&strm, Z_NO_FLUSH);
- Assert(err != Z_STREAM_ERROR); /* state not clobbered */
- switch (err) {
- case Z_NEED_DICT:
- err = Z_DATA_ERROR; /* and fall through */
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- inflateEnd(&strm);
- //return err;
- return 0;
- }
- have = CHUNK - strm.avail_out;
- if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
- inflateEnd(&strm);
- //return Z_ERRNO;
- return 0;
- }
- } while (strm.avail_out == 0);
- Assert(strm.avail_in == 0); /* all input will be used */
-
- /* done when inflate() says it's done */
- } while (err != Z_STREAM_END);
-
- /* clean up and return */
- inflateEnd(&strm);
- return err == Z_STREAM_END ? 1 : 0;
-}
-
/* ===================================
* Unzips a file. 1: success, 0: error
* Adapted from miniunz.c [Celest]
@@ -488,7 +405,7 @@ unsigned long grfio_crc32 (const char *buf, unsigned int len) }
/***********************************************************
- *** File List Sobroutines ***
+ *** File List Subroutines ***
***********************************************************/
/*==========================================
@@ -520,7 +437,7 @@ static void hashinit(void) * File List : File find
*------------------------------------------
*/
-FILELIST *filelist_find(char *fname)
+static FILELIST *filelist_find(char *fname)
{
int hash;
@@ -546,7 +463,7 @@ static FILELIST* filelist_add(FILELIST *entry) int hash;
if (filelist_entrys >= FILELIST_LIMIT) {
- ShowFatalError("filelist limit : filelist_add\n");
+ ShowFatalError("GRF filelist limit reached (filelist_add)!\n");
exit(1);
}
@@ -598,78 +515,6 @@ static void filelist_adjust(void) /***********************************************************
*** Grfio Sobroutines ***
***********************************************************/
-/*==========================================
- * Grfio : Local Resnametable replace
- *------------------------------------------
- */
-static void grfio_resnametable(char *src, char *dest)
-{
- int lop;
- if (localresname == NULL ||
- sscanf(src, "%*5s%s", dest) < 1)
- {
- // if not found copy the unresolved name into buffer
- strcpy(dest, src);
- return;
- }
-
- for (lop = 0; lop < resname_entrys; lop++) {
- if (strcmpi(localresname[lop].src, dest) == 0) {
- sprintf(dest, "data\\%s", localresname[lop].dst);
- return;
- }
- }
-
- return;
-}
-
-/*==========================================
- * Grfio : Local Resnametable Initialize
- *------------------------------------------
- */
-static void grfio_resnameinit (void)
-{
- FILE *fp;
- char *p;
- // max length per entry is 34 in resnametable
- char w1[64], w2[64], restable[256], line[256];
-
- sprintf(restable, "%sdata\\resnametable.txt", data_dir);
- for (p = &restable[0]; *p != 0; p++)
- if (*p == '\\') *p = '/';
-
- fp = fopen(restable,"rb");
- if (fp == NULL) {
- //ShowError("%s not found (grfio_resnameinit)\n", restable);
- return;
- }
-
- while (fgets(line, sizeof(line) - 1, fp)){
- if (sscanf(line, "%[^#]#%[^#]#", w1, w2) != 2)
- continue;
- // only save up necessary resource files
- if (strstr(w1, ".gat") == NULL &&
- strstr(w1, ".txt") == NULL)
- continue;
- if (resname_entrys >= RESNAME_LIMIT)
- break;
- if (resname_entrys >= resname_maxentrys) {
- resname_maxentrys += RESNAME_ADDS;
- localresname = (Resname*) aRealloc (localresname, resname_maxentrys * sizeof(Resname));
- memset(localresname + (resname_maxentrys - RESNAME_ADDS), '\0', sizeof(Resname) * RESNAME_ADDS);
- }
- strcpy(localresname[resname_entrys].src, w1);
- strcpy(localresname[resname_entrys].dst, w2);
- resname_entrys++;
- }
- fclose(fp);
-
- // free up unused sections
- if (resname_maxentrys > resname_entrys) {
- localresname = (Resname*) aRealloc (localresname, resname_entrys * sizeof(Resname));
- resname_maxentrys = resname_entrys;
- }
-}
/*==========================================
* Grfio : Resource file size get
@@ -682,12 +527,11 @@ int grfio_size(char *fname) entry = filelist_find(fname);
if (entry == NULL || entry->gentry < 0) { // LocalFileCheck
- char lfname[256], rname[256], *p;
+ char lfname[256], *p;
FILELIST lentry;
struct stat st;
- grfio_resnametable(fname, rname);
- sprintf(lfname, "%s%s", data_dir, rname);
+ sprintf(lfname, "%s%s", data_dir, fname);
for (p = &lfname[0]; *p != 0; p++)
if (*p=='\\') *p = '/'; // * At the time of Unix
@@ -719,12 +563,10 @@ void* grfio_reads(char *fname, int *size) entry = filelist_find(fname);
if (entry == NULL || entry->gentry <= 0) { // LocalFileCheck
- char lfname[256], rname[256], *p;
+ char lfname[256], *p;
FILELIST lentry;
- // resolve filename into rname
- grfio_resnametable(fname, rname);
- sprintf(lfname, "%s%s", data_dir, rname);
+ sprintf(lfname, "%s%s", data_dir, fname);
for (p = &lfname[0]; *p != 0; p++)
if (*p == '\\') *p = '/'; // * At the time of Unix
@@ -790,15 +632,6 @@ void* grfio_reads(char *fname, int *size) }
/*==========================================
- * Grfio : Resource file read
- *------------------------------------------
- */
-void* grfio_read(char *fname)
-{
- return grfio_reads(fname, NULL);
-}
-
-/*==========================================
* Resource filename decode
*------------------------------------------
*/
@@ -841,7 +674,7 @@ static int grfio_entryread(char *gfname,int gentry) fseek(fp,getlong(grf_header+0x1e),1)) // SEEK_CUR
{
fclose(fp);
- ShowError("%s read error\n",gfname);
+ ShowError("GRF %s read error\n",gfname);
return 2; // 2:file format error
}
@@ -871,7 +704,7 @@ static int grfio_entryread(char *gfname,int gentry) if (type != 0) { // Directory Index ... skip
fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6);
if (strlen(fname) > sizeof(aentry.fn) - 1) {
- ShowFatalError("file name too long : %s\n",fname);
+ ShowFatalError("GRF file name %s is too long\n", fname);
aFree(grf_filelist);
exit(1);
}
@@ -952,7 +785,7 @@ static int grfio_entryread(char *gfname,int gentry) fname = (char*)(grf_filelist+ofs);
if (strlen(fname) > sizeof(aentry.fn)-1) {
- ShowFatalError("grf : file name too long : %s\n",fname);
+ ShowFatalError("GRF file name %s is too long\n", fname);
aFree(grf_filelist);
exit(1);
}
@@ -989,7 +822,7 @@ static int grfio_entryread(char *gfname,int gentry) } else { //****** Grf Other version ******
fclose(fp);
- ShowError("not support grf versions : %04x\n",getlong(grf_header+0x2a));
+ ShowError("GRF version %04x not supported\n",getlong(grf_header+0x2a));
return 4;
}
@@ -1004,52 +837,85 @@ static int grfio_entryread(char *gfname,int gentry) */
static void grfio_resourcecheck(void)
{
- int size;
- char *buf, *ptr;
- char w1[256], w2[256], src[256], dst[256];
+ char w1[256], w2[256], src[256], dst[256], restable[256], line[256];
+ char *ptr, *buf;
FILELIST *entry;
+ int size, i = 0;
+ FILE *fp;
- buf = (char *)grfio_reads("data\\resnametable.txt", &size);
- if (buf == NULL)
- return;
- buf[size] = 0;
+ // read resnametable from data directory and return if successful
+ sprintf(restable, "%sdata\\resnametable.txt", data_dir);
+ for (ptr = &restable[0]; *ptr != 0; ptr++)
+ if (*ptr == '\\') *ptr = '/';
- for (ptr = buf; ptr - buf < size;) {
- if (sscanf(ptr,"%[^#]#%[^#]#",w1,w2) == 2) {
- if (strstr(w2, "bmp")) {
- sprintf(src, "data\\texture\\%s", w1);
- sprintf(dst, "data\\texture\\%s", w2);
- } else {
+ fp = fopen(restable,"rb");
+ if (fp) {
+ while (fgets(line, sizeof(line) - 1, fp)) {
+ if (sscanf(line, "%[^#]#%[^#]#", w1, w2) == 2 &&
+ // we only need the map names and text files
+ (strstr(w2, ".gat") || strstr(w2, ".txt")))
+ {
sprintf(src, "data\\%s", w1);
sprintf(dst, "data\\%s", w2);
+ entry = filelist_find(dst);
+ // create new entries reusing the original's info
+ if (entry != NULL) {
+ FILELIST fentry;
+ memcpy(&fentry, entry, sizeof(FILELIST));
+ strncpy(fentry.fn, src, sizeof(fentry.fn) - 1);
+ filelist_modify(&fentry);
+ i++;
+ }
}
- entry = filelist_find(dst);
- if (entry != NULL) {
- FILELIST fentry;
- memcpy(&fentry, entry, sizeof(FILELIST));
- strncpy(fentry.fn, src, sizeof(fentry.fn) - 1);
- filelist_modify(&fentry);
- } else {
- //ShowError("file not found in data.grf : %s < %s\n",dst,src);
+ }
+ fclose(fp);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, "resnametable.txt");
+ return; // we're done here!
+ }
+
+ // read resnametable from loaded GRF's, only if it cannot be
+ // loaded from the data directory
+ buf = (char *)grfio_reads("data\\resnametable.txt", &size);
+ if (buf) {
+ buf[size] = 0;
+ ptr = buf;
+
+ while (ptr - buf < size) {
+ if (sscanf(ptr, "%[^#]#%[^#]#", w1, w2) == 2 &&
+ (strstr(w2, ".gat") || strstr(w2, ".txt")))
+ {
+ sprintf(src, "data\\%s", w1);
+ sprintf(dst, "data\\%s", w2);
+ entry = filelist_find(dst);
+ if (entry != NULL) {
+ FILELIST fentry;
+ memcpy(&fentry, entry, sizeof(FILELIST));
+ strncpy(fentry.fn, src, sizeof(fentry.fn) - 1);
+ filelist_modify(&fentry);
+ i++;
+ }
}
+ ptr = strchr(ptr,'\n'); // Next line
+ if (!ptr) break;
+ ptr++;
}
- ptr = strchr(ptr,'\n'); // Next line
- if (!ptr) break;
- ptr++;
+ aFree(buf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, "data\\resnametable.txt");
+ return;
}
- aFree(buf);
- filelist_adjust(); // Unnecessary area release of filelist
+
+ //ShowWarning("GRF: No resnametable found! Panic?\n");
}
/*==========================================
* Grfio : Resource add
*------------------------------------------
*/
-#define GENTRY_ADDS 16 // The number increment of gentry_table entries
+#define GENTRY_ADDS 4 // The number increment of gentry_table entries
-int grfio_add(char *fname)
+static int grfio_add(char *fname)
{
- int len,result;
+ int len;
char *buf;
if (gentry_entrys >= GENTRY_LIMIT) {
@@ -1067,12 +933,7 @@ int grfio_add(char *fname) strcpy(buf, fname);
gentry_table[gentry_entrys++] = buf;
- result = grfio_entryread(fname, gentry_entrys - 1);
- if (result == 0)
- // Resource check
- grfio_resourcecheck();
-
- return result;
+ return grfio_entryread(fname, gentry_entrys - 1);
}
/*==========================================
@@ -1095,8 +956,6 @@ void grfio_final(void) }
gentry_table = NULL;
gentry_entrys = gentry_maxentry = 0;
-
- if (localresname) aFree(localresname);
}
/*==========================================
@@ -1139,8 +998,10 @@ void grfio_init(char *fname) //exit(1); // It ends, if a resource cannot read one.
}
- // initialise Resnametable
- grfio_resnameinit();
+ // Unnecessary area release of filelist
+ filelist_adjust();
+ // Resource check
+ grfio_resourcecheck();
return;
}
diff --git a/src/common/grfio.h b/src/common/grfio.h index a7faafc1c..aba9db391 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -6,16 +6,15 @@ void grfio_init(char*); // GRFIO Initialize
void grfio_final(void); // GRFIO Finalize
-int grfio_add(char*); // GRFIO Resource file add
-void* grfio_read(char*); // GRFIO data file read
void* grfio_reads(char*,int*); // GRFIO data file read & size get
+
+#define grfio_read(fn) grfio_reads(fn, NULL)
+
int grfio_size(char*); // GRFIO data file size get
unsigned long grfio_crc32(const char *buf, unsigned int len);
int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen);
int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen);
-int decode_file (FILE *source, FILE *dest);
-
int deflate_file (const char *source, const char *filename);
#endif // _GRFIO_H_
|