Commit message: gallium/tgsi: fix overflow in parse property

In parse_identifier, it doesn't stop copying '*pcur'
untill encounter the NULL. As the 'ret' has a
fixed-size buffer, if the '*pcur' has a long string,
there will be a buffer overflow. This patch avoid this.

Signed-off-by: Li Qiang <liq3ea@gmail.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
CVE: CVE-2017-6209
CWE: CWE-119
Vulnerability description: Stack-based buffer overflow in the parse_identifier function in tgsi_text.c in the TGSI auxiliary module in the Gallium driver in virglrenderer before 0.6.0 allows local guest OS users to cause a denial of service (out-of-bounds array access and QEMU process crash) via vectors related to parsing properties.

Project: virglrenderer
File: tgsi_text.c

static void eat_opt_white( const char **pcur )
{
   while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
      (*pcur)++;
}

Project: virglrenderer
File: tgsi_text.c

static void eat_until_eol( const char **pcur )
{
   while (**pcur != '\0' && **pcur != '\n')
      (*pcur)++;
}

Project: virglrenderer
File: tgsi_text.c

static boolean eat_white( const char **pcur )
{
   const char *cur = *pcur;

   eat_opt_white( pcur );
   return *pcur > cur;
}

Project: virglrenderer
File: tgsi_text.c

static boolean is_alpha_underscore( const char *cur )
{
   return
      (*cur >= 'a' && *cur <= 'z') ||
      (*cur >= 'A' && *cur <= 'Z') ||
      *cur == '_';
}

Project: virglrenderer
File: tgsi_text.c

static boolean is_digit_alpha_underscore( const char *cur )
{
   return is_digit( cur ) || is_alpha_underscore( cur );
}

Project: virglrenderer
File: tgsi_text.c

static boolean parse_int( const char **pcur, int *val )
{
   const char *cur = *pcur;
   int sign = (*cur == '-' ? -1 : 1);

   if (*cur == '+' || *cur == '-')
      cur++;

   if (parse_uint(&cur, (uint *)val)) {
      *val *= sign;
      *pcur = cur;
      return TRUE;
   }

    return FALSE;
 }

Project: virglrenderer
File: tgsi_text.c

static boolean parse_uint( const char **pcur, uint *val )
{
   const char *cur = *pcur;

   if (is_digit( cur )) {
      *val = *cur++ - '0';
      while (is_digit( cur ))
         *val = *val * 10 + *cur++ - '0';
      *pcur = cur;
      return TRUE;
   }
   return FALSE;
}

Project: virglrenderer
File: tgsi_text.c

static boolean str_match_no_case( const char **pcur, const char *str )
{
   const char *cur = *pcur;

   while (*str != '\0' && *str == uprcase( *cur )) {
      str++;
      cur++;
   }
   if (*str == '\0') {
      *pcur = cur;
      return TRUE;
   }
   return FALSE;
}

Project: virglrenderer
File: tgsi_text.c

static boolean str_match_nocase_whole( const char **pcur, const char *str )
{
   const char *cur = *pcur;

   if (str_match_no_case(&cur, str) &&
       !is_digit_alpha_underscore(cur)) {
      *pcur = cur;
      return TRUE;
   }
   return FALSE;
}

Project: virglrenderer
File: tgsi_text.c

streq_nocase_uprcase(const char *str1,
                     const char *str2)
{
   while (*str1 && *str2) {
      if (*str1 != uprcase(*str2))
         return FALSE;
      str1++;
      str2++;
   }
   return *str1 == 0 && *str2 == 0;
}

Project: virglrenderer
File: tgsi_text.c

static char uprcase( char c )
{
   if (c >= 'a' && c <= 'z')
      return c + 'A' - 'a';
   return c;
}