<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 11, 2017 at 2:54 PM, Dan Williams <span dir="ltr"><<a href="mailto:dcbw@redhat.com" target="_blank">dcbw@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, 2017-08-11 at 13:27 -0700, Ben Chan wrote:<br>
> The while loop in mm_charset_get_encoded_len() iterates through each<br>
> valid UTF-8 encoded character in the given NULL-terminated UTF-8<br>
> string.<br>
> It uses g_utf8_find_next_char() to find the position of the next<br>
> character. In case, g_utf8_find_next_char() returns NULL, it tries to<br>
> find the end (i.e. the NULL character) of the string.<br>
><br>
> This patch fixes the following issues in the while loop:<br>
><br>
> 1. The loop uses both 'next' and 'end' to track the position of the<br>
> next<br>
>    character in the string.<br>
><br>
>    When g_utf8_find_next_char() returns a non-NULL value, 'next' is<br>
>    essentially the same as 'end'.<br>
><br>
>    When g_utf8_find_next_char() returns NULL, 'next' remains NULL<br>
> while<br>
>    'end' is adjusted to track the end of the string (but is done<br>
>    incorrectly as described in #2). After the 'p = next' assignment,<br>
> the<br>
>    'while (*p)' check results in a NULL dereference. 'p' should thus<br>
> be<br>
>    set to 'end' instead of 'next'.<br>
><br>
>    'next' is thus redundant and can be removed.<br>
<br>
</span>Agreed.<br>
<span class=""><br>
> 2. When g_utf8_find_next_char() returns NULL and 'end' is adjusted to<br>
>    track the end of string, the 'while (*end++)' loop stops when<br>
> finding<br>
>    the NULL character, but 'end' is advanced past the NULL character.<br>
>    After the 'p = end' assignment, the 'while (*p)' check results in<br>
> a<br>
>    NULL dereference.<br>
<br>
</span>Yep.<br>
<span class=""><br>
>    'while (*++end)' should be used instead given that 'p' doesn't<br>
> point<br>
>    to a NULL character when 'end = p' happens. 'end' will be updated<br>
> to<br>
>    point to the NULL character. After the 'p = end' assignment (fixed<br>
> in<br>
>    #1), the 'while (*p)' check will properly stop the loop.<br>
> ---<br>
> Hi Dan and Aleksander,<br>
><br>
> I was a bit confused by the purpose of 'next' and 'end', and the part<br>
> where it<br>
> skips through the end of the string when it fails to find the next<br>
> UTF-8<br>
> encoded character. The patch is based on what I guess the intention<br>
> of the<br>
> code. Please let me know if I've missed anything.<br>
<br>
</span>I think I wrote this code.  I'm now confused about the purpose of end<br>
and next.  You're not alone.<br>
<br>
I think we just get lucky here; perhaps there's always another byte at<br>
the end of the string that doesn't cause a segfault due to padding or<br>
memory allocation weirdness or something.<br>
<span class=""><br>
> Also, We should try enumerate some test cases for it. Maybe in a<br>
> follow-up patch.<br>
<br>
</span>I suspect we'd catch it under valgrind.  NetworkManager has valgrind<br>
test support, and while it's a bit painful sometimes (because we have<br>
to update the false-positive filter regularly due to glib/GObject<br>
changes) and it makes the tests go a lot slower, it definitely can<br>
catch this kind of thing.<br>
<br></blockquote><div><br></div><div>Agreed. I seldom send/receive SMS, so probably haven't hit this code path under Valgrind or AddressSanitizer. I've been experimenting with clang static analyzer and got some useful results.... in case you and Aleksander was wondering why I submitted all these random patches :)  There are some false positives but I'm happy with the results so far.  Perhaps we could incorporate Clang tool flow in the Jenkins setup.  The online Coverity scan also looks interesting, but I haven't got a chance to look into that yet.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
One more comment below...<br>
<span class=""><br>
> Thanks,<br>
> Ben<br>
><br>
>  src/mm-charsets.c | 8 ++++----<br>
>  1 file changed, 4 insertions(+), 4 deletions(-)<br>
><br>
> diff --git a/src/mm-charsets.c b/src/mm-charsets.c<br>
> index 191789d7..7ba31aa5 100644<br>
> --- a/src/mm-charsets.c<br>
> +++ b/src/mm-charsets.c<br>
> @@ -595,7 +595,7 @@ mm_charset_get_encoded_len (const char *utf8,<br>
>                              <wbr>MMModemCharset charset,<br>
>                              <wbr>guint *out_unsupported)<br>
>  {<br>
> -    const char *p = utf8, *next;<br>
> +    const char *p = utf8;<br>
>      guint len = 0, unsupported = 0;<br>
>      SubsetEntry *e;<br>
>  <br>
> @@ -618,17 +618,17 @@ mm_charset_get_encoded_len (const char *utf8,<br>
>  <br>
>          c = g_utf8_get_char_validated (p, -1);<br>
>          g_return_val_if_fail (c != (gunichar) -1, 0);<br>
> -        end = next = g_utf8_find_next_char (p, NULL);<br>
> +        end = g_utf8_find_next_char (p, NULL);<br>
>          if (end == NULL) {<br>
>              /* Find the end... */<br>
><br>
</span>Could you update the comment to say "find the string-terminating NULL"<br>
or something like that?<br>
<span class="im HOEnZb"><br></span></blockquote><div><br></div><div>Sure, updated in v2.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="im HOEnZb">
>              end = p;<br>
> -            while (*end++);<br>
> +            while (*++end);<br>
>          }<br>
>  <br>
>          if (!e->func (c, p, (end - p), &clen))<br>
>              unsupported++;<br>
>          len += clen;<br>
> -        p = next;<br>
> +        p = end;<br>
>      }<br>
>  <br>
>      if (out_unsupported)<br>
</span><div class="HOEnZb"><div class="h5">______________________________<wbr>_________________<br>
ModemManager-devel mailing list<br>
<a href="mailto:ModemManager-devel@lists.freedesktop.org">ModemManager-devel@lists.<wbr>freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/modemmanager-<wbr>devel</a><br>
</div></div></blockquote></div><br></div></div>