udf: Fix conversion of 'dstring' fields to UTF8
Commit9293fcfbc1
("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, commit484a10f493
("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: Andrew Gabbasov <andrew_gabbasov@mentor.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
95d0c4277c
commit
c26f6c6157
|
@ -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 @@ try_again:
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue