summaryrefslogtreecommitdiffstats
path: root/kernel/fs/udf/unicode.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fs/udf/unicode.c')
-rw-r--r--kernel/fs/udf/unicode.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/kernel/fs/udf/unicode.c b/kernel/fs/udf/unicode.c
index b84fee372..e788a05aa 100644
--- a/kernel/fs/udf/unicode.c
+++ b/kernel/fs/udf/unicode.c
@@ -68,21 +68,16 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
/*
* udf_build_ustr_exact
*/
-static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+static void udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
{
- if ((!dest) || (!ptr) || (!exactsize))
- return -1;
-
memset(dest, 0, sizeof(struct ustr));
dest->u_cmpID = ptr[0];
dest->u_len = exactsize - 1;
memcpy(dest->u_name, ptr + 1, exactsize - 1);
-
- return 0;
}
/*
- * udf_ocu_to_utf8
+ * udf_CS0toUTF8
*
* PURPOSE
* Convert OSTA Compressed Unicode to the UTF-8 equivalent.
@@ -94,7 +89,7 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
* both of type "struct ustr *"
*
* POST-CONDITIONS
- * <return> Zero on success.
+ * <return> >= 0 on success.
*
* HISTORY
* November 12, 1997 - Andrew E. Mileski
@@ -117,7 +112,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
memset(utf_o, 0, sizeof(struct ustr));
pr_err("unknown compression code (%d) stri=%s\n",
cmp_id, ocu_i->u_name);
- return 0;
+ return -EINVAL;
}
ocu = ocu_i->u_name;
@@ -133,11 +128,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
if (c < 0x80U)
utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
else if (c < 0x800U) {
+ if (utf_o->u_len > (UDF_NAME_LEN - 4))
+ break;
utf_o->u_name[utf_o->u_len++] =
(uint8_t)(0xc0 | (c >> 6));
utf_o->u_name[utf_o->u_len++] =
(uint8_t)(0x80 | (c & 0x3f));
} else {
+ if (utf_o->u_len > (UDF_NAME_LEN - 5))
+ break;
utf_o->u_name[utf_o->u_len++] =
(uint8_t)(0xe0 | (c >> 12));
utf_o->u_name[utf_o->u_len++] =
@@ -154,7 +153,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
/*
*
- * udf_utf8_to_ocu
+ * udf_UTF8toCS0
*
* PURPOSE
* Convert UTF-8 to the OSTA Compressed Unicode equivalent.
@@ -178,17 +177,22 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
{
unsigned c, i, max_val, utf_char;
- int utf_cnt, u_len;
+ int utf_cnt, u_len, u_ch;
memset(ocu, 0, sizeof(dstring) * length);
ocu[0] = 8;
max_val = 0xffU;
+ u_ch = 1;
try_again:
u_len = 0U;
utf_char = 0U;
utf_cnt = 0U;
for (i = 0U; i < utf->u_len; i++) {
+ /* Name didn't fit? */
+ if (u_len + 1 + u_ch >= length)
+ return 0;
+
c = (uint8_t)utf->u_name[i];
/* Complete a multi-byte UTF-8 character */
@@ -230,6 +234,7 @@ try_again:
if (max_val == 0xffU) {
max_val = 0xffffU;
ocu[0] = (uint8_t)0x10U;
+ u_ch = 2;
goto try_again;
}
goto error_out;
@@ -270,7 +275,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
memset(utf_o, 0, sizeof(struct ustr));
pr_err("unknown compression code (%d) stri=%s\n",
cmp_id, ocu_i->u_name);
- return 0;
+ return -EINVAL;
}
ocu = ocu_i->u_name;
@@ -282,7 +287,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
c = (c << 8) | ocu[i++];
len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len],
- UDF_NAME_LEN - utf_o->u_len);
+ UDF_NAME_LEN - 2 - utf_o->u_len);
/* Valid character? */
if (len >= 0)
utf_o->u_len += len;
@@ -300,15 +305,19 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni,
int len;
unsigned i, max_val;
uint16_t uni_char;
- int u_len;
+ int u_len, u_ch;
memset(ocu, 0, sizeof(dstring) * length);
ocu[0] = 8;
max_val = 0xffU;
+ u_ch = 1;
try_again:
u_len = 0U;
for (i = 0U; i < uni->u_len; i++) {
+ /* Name didn't fit? */
+ if (u_len + 1 + u_ch >= length)
+ return 0;
len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char);
if (!len)
continue;
@@ -321,6 +330,7 @@ try_again:
if (uni_char > max_val) {
max_val = 0xffffU;
ocu[0] = (uint8_t)0x10U;
+ u_ch = 2;
goto try_again;
}
@@ -338,43 +348,51 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen,
uint8_t *dname, int dlen)
{
struct ustr *filename, *unifilename;
- int len = 0;
+ int ret;
+
+ if (!slen)
+ return -EIO;
filename = kmalloc(sizeof(struct ustr), GFP_NOFS);
if (!filename)
- return 0;
+ return -ENOMEM;
unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS);
- if (!unifilename)
+ if (!unifilename) {
+ ret = -ENOMEM;
goto out1;
+ }
- if (udf_build_ustr_exact(unifilename, sname, slen))
- goto out2;
-
+ udf_build_ustr_exact(unifilename, sname, slen);
if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) {
- if (!udf_CS0toUTF8(filename, unifilename)) {
+ ret = udf_CS0toUTF8(filename, unifilename);
+ if (ret < 0) {
udf_debug("Failed in udf_get_filename: sname = %s\n",
sname);
goto out2;
}
} else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) {
- if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename,
- unifilename)) {
+ ret = udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename,
+ unifilename);
+ if (ret < 0) {
udf_debug("Failed in udf_get_filename: sname = %s\n",
sname);
goto out2;
}
} else
- goto out2;
+ BUG();
- len = udf_translate_to_linux(dname, dlen,
+ ret = udf_translate_to_linux(dname, dlen,
filename->u_name, filename->u_len,
unifilename->u_name, unifilename->u_len);
+ /* Zero length filename isn't valid... */
+ if (ret == 0)
+ ret = -EINVAL;
out2:
kfree(unifilename);
out1:
kfree(filename);
- return len;
+ return ret;
}
int udf_put_filename(struct super_block *sb, const uint8_t *sname,