summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-01-05 23:49:51 (GMT)
committer John Mark Bell <jmb@netsurf-browser.org>2009-01-05 23:49:51 (GMT)
commitce231ac3f456d2e92730d344cda1578eaf1d8add (patch)
treead227ae870e2ce38beae910b159de41f79e7d842
parent5946e302829ff1ebd4905dbf2fa8021ed24cbedc (diff)
downloadiconv-ce231ac3f456d2e92730d344cda1578eaf1d8add.tar.gz
iconv-ce231ac3f456d2e92730d344cda1578eaf1d8add.tar.bz2
Improve error reporting from iconv_eightbit_new. This means we correctly return EINVAL if we can't find a mapping table, rather than assuming ENOMEM.
Bump version number while we're at it. svn path=/trunk/iconv/; revision=5962
-rw-r--r--doc/ChangeLog5
-rw-r--r--module/header.cmhg2
-rw-r--r--module/header.h6
-rw-r--r--src/eightbit.c26
-rw-r--r--src/iconv.c91
-rw-r--r--src/internal.h7
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 */