diff options
Diffstat (limited to 'fs/udf/unicode.c')
-rw-r--r-- | fs/udf/unicode.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 9fdf8c93c58e..cefa8c8913e6 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c | |||
@@ -254,7 +254,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, | |||
254 | { | 254 | { |
255 | const uint8_t *ocu; | 255 | const uint8_t *ocu; |
256 | uint8_t cmp_id, ocu_len; | 256 | uint8_t cmp_id, ocu_len; |
257 | int i; | 257 | int i, len; |
258 | 258 | ||
259 | 259 | ||
260 | ocu_len = ocu_i->u_len; | 260 | ocu_len = ocu_i->u_len; |
@@ -279,8 +279,13 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, | |||
279 | if (cmp_id == 16) | 279 | if (cmp_id == 16) |
280 | c = (c << 8) | ocu[i++]; | 280 | c = (c << 8) | ocu[i++]; |
281 | 281 | ||
282 | utf_o->u_len += nls->uni2char(c, &utf_o->u_name[utf_o->u_len], | 282 | len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len], |
283 | UDF_NAME_LEN - utf_o->u_len); | 283 | UDF_NAME_LEN - utf_o->u_len); |
284 | /* Valid character? */ | ||
285 | if (len >= 0) | ||
286 | utf_o->u_len += len; | ||
287 | else | ||
288 | utf_o->u_name[utf_o->u_len++] = '?'; | ||
284 | } | 289 | } |
285 | utf_o->u_cmpID = 8; | 290 | utf_o->u_cmpID = 8; |
286 | 291 | ||
@@ -290,7 +295,8 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, | |||
290 | static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, | 295 | static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, |
291 | int length) | 296 | int length) |
292 | { | 297 | { |
293 | unsigned len, i, max_val; | 298 | int len; |
299 | unsigned i, max_val; | ||
294 | uint16_t uni_char; | 300 | uint16_t uni_char; |
295 | int u_len; | 301 | int u_len; |
296 | 302 | ||
@@ -302,8 +308,13 @@ try_again: | |||
302 | u_len = 0U; | 308 | u_len = 0U; |
303 | for (i = 0U; i < uni->u_len; i++) { | 309 | for (i = 0U; i < uni->u_len; i++) { |
304 | len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char); | 310 | len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char); |
305 | if (len <= 0) | 311 | if (!len) |
306 | continue; | 312 | continue; |
313 | /* Invalid character, deal with it */ | ||
314 | if (len < 0) { | ||
315 | len = 1; | ||
316 | uni_char = '?'; | ||
317 | } | ||
307 | 318 | ||
308 | if (uni_char > max_val) { | 319 | if (uni_char > max_val) { |
309 | max_val = 0xffffU; | 320 | max_val = 0xffffU; |
@@ -324,34 +335,43 @@ try_again: | |||
324 | int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | 335 | int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, |
325 | int flen) | 336 | int flen) |
326 | { | 337 | { |
327 | struct ustr filename, unifilename; | 338 | struct ustr *filename, *unifilename; |
328 | int len; | 339 | int len = 0; |
329 | 340 | ||
330 | if (udf_build_ustr_exact(&unifilename, sname, flen)) | 341 | filename = kmalloc(sizeof(struct ustr), GFP_NOFS); |
342 | if (!filename) | ||
331 | return 0; | 343 | return 0; |
332 | 344 | ||
345 | unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS); | ||
346 | if (!unifilename) | ||
347 | goto out1; | ||
348 | |||
349 | if (udf_build_ustr_exact(unifilename, sname, flen)) | ||
350 | goto out2; | ||
351 | |||
333 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { | 352 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { |
334 | if (!udf_CS0toUTF8(&filename, &unifilename)) { | 353 | if (!udf_CS0toUTF8(filename, unifilename)) { |
335 | udf_debug("Failed in udf_get_filename: sname = %s\n", | 354 | udf_debug("Failed in udf_get_filename: sname = %s\n", |
336 | sname); | 355 | sname); |
337 | return 0; | 356 | goto out2; |
338 | } | 357 | } |
339 | } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { | 358 | } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { |
340 | if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, &filename, | 359 | if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename, |
341 | &unifilename)) { | 360 | unifilename)) { |
342 | udf_debug("Failed in udf_get_filename: sname = %s\n", | 361 | udf_debug("Failed in udf_get_filename: sname = %s\n", |
343 | sname); | 362 | sname); |
344 | return 0; | 363 | goto out2; |
345 | } | 364 | } |
346 | } else | 365 | } else |
347 | return 0; | 366 | goto out2; |
348 | 367 | ||
349 | len = udf_translate_to_linux(dname, filename.u_name, filename.u_len, | 368 | len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, |
350 | unifilename.u_name, unifilename.u_len); | 369 | unifilename->u_name, unifilename->u_len); |
351 | if (len) | 370 | out2: |
352 | return len; | 371 | kfree(unifilename); |
353 | 372 | out1: | |
354 | return 0; | 373 | kfree(filename); |
374 | return len; | ||
355 | } | 375 | } |
356 | 376 | ||
357 | int udf_put_filename(struct super_block *sb, const uint8_t *sname, | 377 | int udf_put_filename(struct super_block *sb, const uint8_t *sname, |