lkml.org 
[lkml]   [2016]   [Feb]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.14 44/70] udf: Check output buffer length when converting name to CS0
    Date
    3.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Andrew Gabbasov <andrew_gabbasov@mentor.com>

    commit bb00c898ad1ce40c4bb422a8207ae562e9aea7ae upstream.

    If a name contains at least some characters with Unicode values
    exceeding single byte, the CS0 output should have 2 bytes per character.
    And if other input characters have single byte Unicode values, then
    the single input byte is converted to 2 output bytes, and the length
    of output becomes larger than the length of input. And if the input
    name is long enough, the output length may exceed the allocated buffer
    length.

    All this means that conversion from UTF8 or NLS to CS0 requires
    checking of output length in order to stop when it exceeds the given
    output buffer size.

    [JK: Make code return -ENAMETOOLONG instead of silently truncating the
    name]

    Signed-off-by: Andrew Gabbasov <andrew_gabbasov@mentor.com>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/udf/unicode.c | 15 +++++++++++++--
    1 file changed, 13 insertions(+), 2 deletions(-)

    --- a/fs/udf/unicode.c
    +++ b/fs/udf/unicode.c
    @@ -181,17 +181,22 @@ int udf_CS0toUTF8(struct ustr *utf_o, co
    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 */
    @@ -233,6 +238,7 @@ try_again:
    if (max_val == 0xffU) {
    max_val = 0xffffU;
    ocu[0] = (uint8_t)0x10U;
    + u_ch = 2;
    goto try_again;
    }
    goto error_out;
    @@ -303,15 +309,19 @@ static int udf_NLStoCS0(struct nls_table
    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;
    @@ -324,6 +334,7 @@ try_again:
    if (uni_char > max_val) {
    max_val = 0xffffU;
    ocu[0] = (uint8_t)0x10U;
    + u_ch = 2;
    goto try_again;
    }


    \
     
     \ /
      Last update: 2016-02-24 06:21    [W:4.113 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site