Commit c26f6c61 authored by Andrew Gabbasov's avatar Andrew Gabbasov Committed by Jan Kara

udf: Fix conversion of 'dstring' fields to UTF8

Commit 9293fcfb
("udf: Remove struct ustr as non-needed intermediate storage"),
while getting rid of 'struct ustr', does not take any special care
of 'dstring' fields and effectively use fixed field length instead
of actual string length, encoded in the last byte of the field.

Also, commit 484a10f4
("udf: Merge linux specific translation into CS0 conversion function")
introduced checking of the length of the string being converted,
requiring proper alignment to number of bytes constituing each
character.

The UDF volume identifier is represented as a 32-bytes 'dstring',
and needs to be converted from CS0 to UTF8, while mounting UDF
filesystem. The changes in mentioned commits can in some cases
lead to incorrect handling of volume identifier:
- if the actual string in 'dstring' is of maximal length and
does not have zero bytes separating it from dstring encoded
length in last byte, that last byte may be included in conversion,
thus making incorrect resulting string;
- if the identifier is encoded with 2-bytes characters (compression
code is 16), the length of 31 bytes (32 bytes of field length minus
1 byte of compression code), taken as the string length, is reported
as an incorrect (unaligned) length, and the conversion fails, which
in its turn leads to volume mounting failure.

This patch introduces handling of 'dstring' encoded length field
in udf_CS0toUTF8 function, that is used in all and only cases
when 'dstring' fields are converted. Currently these cases are
processing of Volume Identifier and Volume Set Identifier fields.
The function is also renamed to udf_dstrCS0toUTF8 to distinctly
indicate that it handles 'dstring' input.
Signed-off-by: default avatarAndrew Gabbasov <andrew_gabbasov@mentor.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 95d0c427
......@@ -919,14 +919,14 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
#endif
}
ret = udf_CS0toUTF8(outstr, 31, pvoldesc->volIdent, 32);
ret = udf_dstrCS0toUTF8(outstr, 31, pvoldesc->volIdent, 32);
if (ret < 0)
goto out_bh;
strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident);
ret = udf_CS0toUTF8(outstr, 127, pvoldesc->volSetIdent, 128);
ret = udf_dstrCS0toUTF8(outstr, 127, pvoldesc->volSetIdent, 128);
if (ret < 0)
goto out_bh;
......
......@@ -212,7 +212,7 @@ extern int udf_get_filename(struct super_block *, const uint8_t *, int,
uint8_t *, int);
extern int udf_put_filename(struct super_block *, const uint8_t *, int,
uint8_t *, int);
extern int udf_CS0toUTF8(uint8_t *, int, const uint8_t *, int);
extern int udf_dstrCS0toUTF8(uint8_t *, int, const uint8_t *, int);
/* ialloc.c */
extern void udf_free_inode(struct inode *);
......
......@@ -335,9 +335,21 @@ static int udf_name_to_CS0(uint8_t *ocu, int ocu_max_len,
return u_len;
}
int udf_CS0toUTF8(uint8_t *utf_o, int o_len, const uint8_t *ocu_i, int i_len)
int udf_dstrCS0toUTF8(uint8_t *utf_o, int o_len,
const uint8_t *ocu_i, int i_len)
{
return udf_name_from_CS0(utf_o, o_len, ocu_i, i_len,
int s_len = 0;
if (i_len > 0) {
s_len = ocu_i[i_len - 1];
if (s_len >= i_len) {
pr_err("incorrect dstring lengths (%d/%d)\n",
s_len, i_len);
return -EINVAL;
}
}
return udf_name_from_CS0(utf_o, o_len, ocu_i, s_len,
udf_uni2char_utf8, 0);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment