[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Libidn serious bug on Windows x64

From: Evgeny Grin
Subject: Re: Libidn serious bug on Windows x64
Date: Thu, 21 Jul 2016 23:59:58 +0300
User-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0

On 21.07.2016 23:25, Evgeny Grin wrote:
> On 20.07.2016 20:03, Simon Josefsson wrote:
>> Evgeny Grin <address@hidden> writes:
>>> Hi!
>>> While debugging cURL on Windows x64 crash with simple run of "curl -v
>>> http://яндекс.рф";, I discovered that crash caused by calling
>>> tld_check_lz(). Further investigations reveal pointer to size_t is cast
>>> to pointer to long in stringprep_utf8_to_ucs4() which in invalid on
>>> Win64. As result - very high number is stored in items_written and in
>>> tld_get_4() dereferenced an invalid pointer.
>>> I can't make a minimal example to illustrate it as in minimal example
>>> initial nullifying hides the problem. Hope that invalid casting is
>>> obvious problem.
>> Hello.  Does this problem still exist with 1.32?  What size does
>> 'size_t' and 'long' have on Windows x64?
> Yes, the same bug is present in 1.32, 1.33 and in current git master.
> Currently libidn keep crashing on Windows.
> MinGW package includes my patches to prevent crashing:
> Generally, you can't assume that sizeof(int) == sizeof(long) or
> sizeof(long) == sizeof(long long) or sizeof(long) == sizeof(void*)
> On Windows x64 sizeof(int) == 4, sizeof(long) == 4, sizeof(long long) ==
> 8, sizeof(void*) == 8.
> But casting pointer to one type to pointer to other type is bad idea in
> general, unless you 100% sure that such casting is ALWAYS and ANYWHERE
> valid.
> I sent already some patches for fixing this bug.
> Additional (unrelated) fixes attached.

Main fix for crash is here:

Crash path:
Client calls tld_check_lz()
tld_check_lz() calls tld_check_8z()
tld_check_8z() calls stringprep_utf8_to_ucs4() with last parameter
pointer to size_t type _uninitialized_ variable 'ilen'.
stringprep_utf8_to_ucs4() calls g_utf8_to_ucs4_fast() with casting
pointer to size_t (8 bytes variable) to pointer to long (4 bytes variable)
g_utf8_to_ucs4_fast() writes only 4 bytes to 'items_written' (leaving
another 4 bytes uninitialized).
stringprep_utf8_to_ucs4() returns to tld_check_8z(): 'ilen' contains
lower 4 bytes with valid data and high 4 bytes with random data.
tld_check_8z() calls tld_check_4() with `ilen' specifies several
gigabytes of data to be processed.
Read memory outside the buffer.

And I'd like to point attention to other bug:
Currently only tld_check_4() and tld_check_4z() return valid position in
tld_check_8z(), tld_check_lz() return same number as tld_check_4(), but
this position is incorrect for UTF-8 and for local encoding.

Best Wishes,
Evgeny Grin

Attachment: signature.asc
Description: OpenPGP digital signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]