diff options
-rw-r--r-- | doc/ChangeLog | 5 | ||||
-rw-r--r-- | module/header.cmhg | 2 | ||||
-rw-r--r-- | module/header.h | 6 | ||||
-rw-r--r-- | src/eightbit.c | 26 | ||||
-rw-r--r-- | src/iconv.c | 91 | ||||
-rw-r--r-- | src/internal.h | 7 |
6 files changed, 80 insertions, 57 deletions
diff --git a/doc/ChangeLog b/doc/ChangeLog index 597187e..b936a50 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -97,4 +97,9 @@ Iconv Changelog - Fix handling of illegal UTF-8 byte sequences - Fix handling of incomplete multibyte input sequences. +0.11 XX-XXX-2009 +---------------- + + - Detect missing mapping file when using 8bit codecs. This prevents spurious + memory exhaustion errors. diff --git a/module/header.cmhg b/module/header.cmhg index 0fdfa24..3e191b5 100644 --- a/module/header.cmhg +++ b/module/header.cmhg @@ -1,4 +1,4 @@ -help-string: Iconv 0.10 +help-string: Iconv 0.11 title-string: Iconv diff --git a/module/header.h b/module/header.h index 3e34738..8db5057 100644 --- a/module/header.h +++ b/module/header.h @@ -11,10 +11,10 @@ #define Module_Title "Iconv" #define Module_Help "Iconv" -#define Module_VersionString "0.10" -#define Module_VersionNumber 10 +#define Module_VersionString "0.11" +#define Module_VersionNumber 11 #ifndef Module_Date -#define Module_Date "29 Nov 2008" +#define Module_Date "05 Jan 2009" #endif #ifdef __cplusplus diff --git a/src/eightbit.c b/src/eightbit.c index da1cd4b..f201f31 100644 --- a/src/eightbit.c +++ b/src/eightbit.c @@ -21,7 +21,7 @@ struct table_entry { /* Table should be ordered by enc_num */ static const struct table_entry mapping_table[] = { - { "US-ASCII", 0 }, + { "US-ASCII", NULL }, { "HP-ROMAN8", "HPR8" }, { "MACINTOSH", "Apple" DIR_SEP "Roman"}, { "IBM437", "Microsoft" DIR_SEP "CP437" }, @@ -224,9 +224,12 @@ int iconv_eightbit_write(struct encoding_context *e, UCS4 c, * Load an 8bit encoding * * \param enc_num The encoding number to load - * \return Pointer to lookup table for encoding, or NULL on error + * \param table Pointer to location to receive LUT + * \return EIGHTBIT_OK on success, + * _NOMEM on memory exhaustion, + * or _UNKNOWN if a LUT cannot be found. */ -unsigned short *iconv_eightbit_new(int enc_num) +eightbit_ret iconv_eightbit_new(int enc_num, unsigned short **table) { const char *filename = NULL; const char *name; @@ -237,13 +240,14 @@ unsigned short *iconv_eightbit_new(int enc_num) name = mibenum_to_name(enc_num); if (!name) - return NULL; + return EIGHTBIT_UNKNOWN; /* Lookup filename in table */ for (i = 0; i != TABLE_SIZE; i++) if (strcasecmp(mapping_table[i].canon, name) == 0) { - if (mapping_table[i].filename == 0) - return NULL; + /* Found in the map, but no LUT needed (i.e. ASCII) */ + if (mapping_table[i].filename == NULL) + return EIGHTBIT_OK; filename = get_table_path(mapping_table[i].filename); @@ -255,7 +259,7 @@ unsigned short *iconv_eightbit_new(int enc_num) /* Open */ fp = fopen(filename, "rb"); if (!fp) { - return NULL; + return EIGHTBIT_UNKNOWN; } /* Get extent */ @@ -266,21 +270,23 @@ unsigned short *iconv_eightbit_new(int enc_num) /* Unexpected length => give up */ if (len != 256) { fclose(fp); - return NULL; + return EIGHTBIT_UNKNOWN; } /* Create buffer */ ret = calloc(128, sizeof(short)); if (!ret) { fclose(fp); - return NULL; + return EIGHTBIT_NOMEM; } fread(ret, 128, sizeof(short), fp); fclose(fp); - return ret; + *table = ret; + + return EIGHTBIT_OK; } /** diff --git a/src/iconv.c b/src/iconv.c index dccd23b..45bd15f 100644 --- a/src/iconv.c +++ b/src/iconv.c @@ -67,6 +67,7 @@ iconv_t iconv_open(const char *tocode, const char *fromcode) char totemp[128], fromtemp[128]; const char *slash; unsigned int len; + eightbit_ret error; /* can't do anything without these */ if (!tocode || !fromcode) { @@ -184,60 +185,66 @@ iconv_t iconv_open(const char *tocode, const char *fromcode) } /* bit 30 set indicates that this is an 8bit encoding */ - if (from & (1<<30)) - e->intab = iconv_eightbit_new(from & ~(1<<30)); - else { + if (from & (1<<30)) { + error = iconv_eightbit_new(from & ~(1<<30), &e->intab); + if (error != EIGHTBIT_OK) { + free(e); + errno = (error == EIGHTBIT_NOMEM) ? ENOMEM : EINVAL; + return (iconv_t)(-1); + } + } else { e->in = encoding_new(from, encoding_READ); - if (e->in) { - /* Set encoding flags */ - unsigned int flags = 0; - if (from_force_le) - flags |= encoding_FLAG_LITTLE_ENDIAN; + if (e->in == NULL) { + free(e); + errno = ENOMEM; /* Assume memory exhaustion */ + return (iconv_t)(-1); + } - if (from == csUnicode || from_no_bom) - flags |= encoding_FLAG_NO_HEADER; + /* Set encoding flags */ + unsigned int flags = 0; + if (from_force_le) + flags |= encoding_FLAG_LITTLE_ENDIAN; - encoding_set_flags(e->in, flags, flags); + if (from == csUnicode || from_no_bom) + flags |= encoding_FLAG_NO_HEADER; - e->inflags = flags; - } - } + encoding_set_flags(e->in, flags, flags); - /* neither created => memory error or somesuch. assume ENOMEM */ - /* no table is ever generated for ASCII */ - if (!e->in && !e->intab && (from & ~(1<<30)) != csASCII) { - free(e); - errno = ENOMEM; - return (iconv_t)(-1); + e->inflags = flags; } - if (to & (1<<30)) - e->outtab = iconv_eightbit_new(to & ~(1<<30)); - else { + if (to & (1<<30)) { + error = iconv_eightbit_new(to & ~(1<<30), &e->outtab); + if (error != EIGHTBIT_OK) { + if (e->in) + encoding_delete(e->in); + iconv_eightbit_delete(e); + free(e); + errno = (error == EIGHTBIT_NOMEM) ? ENOMEM : EINVAL; + return (iconv_t)(-1); + } + } else { e->out = encoding_new(to, encoding_WRITE_STRICT); - if (e->out) { - /* Set encoding flags */ - unsigned int flags = 0; - if (to_force_le) - flags |= encoding_FLAG_LITTLE_ENDIAN; + if (e->out == NULL) { + if (e->in) + encoding_delete(e->in); + iconv_eightbit_delete(e); + free(e); + errno = ENOMEM; /* Assume memory exhaustion */ + return (iconv_t)(-1); + } - if (to == csUnicode || to_no_bom) - flags |= encoding_FLAG_NO_HEADER; + /* Set encoding flags */ + unsigned int flags = 0; + if (to_force_le) + flags |= encoding_FLAG_LITTLE_ENDIAN; - encoding_set_flags(e->out, flags, flags); + if (to == csUnicode || to_no_bom) + flags |= encoding_FLAG_NO_HEADER; - e->outflags = flags; - } - } + encoding_set_flags(e->out, flags, flags); - /* neither created => ENOMEM */ - if (!e->out && !e->outtab && (to & ~(1<<30)) != csASCII) { - if (e->in) - encoding_delete(e->in); - iconv_eightbit_delete(e); - free(e); - errno = ENOMEM; - return (iconv_t)(-1); + e->outflags = flags; } /* add to list */ diff --git a/src/internal.h b/src/internal.h index eb11589..42efefe 100644 --- a/src/internal.h +++ b/src/internal.h @@ -34,13 +34,18 @@ struct encoding_context { }; /* in eightbit.c */ +typedef enum eightbit_ret { + EIGHTBIT_OK, + EIGHTBIT_UNKNOWN, + EIGHTBIT_NOMEM +} eightbit_ret; int iconv_eightbit_number_from_name(const char *name); unsigned iconv_eightbit_read(struct encoding_context *e, int (*callback)(void *handle, UCS4 c), const char *s, unsigned int n, void *handle); int iconv_eightbit_write(struct encoding_context *e, UCS4 c, char **buf, int *bufsize); -unsigned short *iconv_eightbit_new(int enc_num); +eightbit_ret iconv_eightbit_new(int enc_num, unsigned short **table); void iconv_eightbit_delete(struct encoding_context *e); /* in alias.c */ |