tools/pcre/pcre_valid_utf8.c
author John Schoenick <john@pointysoftware.net>
Wed Jun 01 20:36:16 2011 -0400 (2011-06-01)
changeset 3292 f428ffc8a3fe
parent 2762 d2d467bf1b5a
child 3831 babd0eee3c5e
permissions -rw-r--r--
Fixed regression in FindEntityByClassname from bug 4899 (bug 4941, r=predcrab).
dvander@2762
     1
/*************************************************
dvander@2762
     2
*      Perl-Compatible Regular Expressions       *
dvander@2762
     3
*************************************************/
dvander@2762
     4
dvander@2762
     5
/* PCRE is a library of functions to support regular expressions whose syntax
dvander@2762
     6
and semantics are as close as possible to those of the Perl 5 language.
dvander@2762
     7
dvander@2762
     8
                       Written by Philip Hazel
dvander@2762
     9
           Copyright (c) 1997-2009 University of Cambridge
dvander@2762
    10
dvander@2762
    11
-----------------------------------------------------------------------------
dvander@2762
    12
Redistribution and use in source and binary forms, with or without
dvander@2762
    13
modification, are permitted provided that the following conditions are met:
dvander@2762
    14
dvander@2762
    15
    * Redistributions of source code must retain the above copyright notice,
dvander@2762
    16
      this list of conditions and the following disclaimer.
dvander@2762
    17
dvander@2762
    18
    * Redistributions in binary form must reproduce the above copyright
dvander@2762
    19
      notice, this list of conditions and the following disclaimer in the
dvander@2762
    20
      documentation and/or other materials provided with the distribution.
dvander@2762
    21
dvander@2762
    22
    * Neither the name of the University of Cambridge nor the names of its
dvander@2762
    23
      contributors may be used to endorse or promote products derived from
dvander@2762
    24
      this software without specific prior written permission.
dvander@2762
    25
dvander@2762
    26
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
dvander@2762
    27
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
dvander@2762
    28
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
dvander@2762
    29
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
dvander@2762
    30
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
dvander@2762
    31
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
dvander@2762
    32
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
dvander@2762
    33
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
dvander@2762
    34
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
dvander@2762
    35
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
dvander@2762
    36
POSSIBILITY OF SUCH DAMAGE.
dvander@2762
    37
-----------------------------------------------------------------------------
dvander@2762
    38
*/
dvander@2762
    39
dvander@2762
    40
dvander@2762
    41
/* This module contains an internal function for validating UTF-8 character
dvander@2762
    42
strings. */
dvander@2762
    43
dvander@2762
    44
dvander@2762
    45
#ifdef HAVE_CONFIG_H
dvander@2762
    46
#include "config.h"
dvander@2762
    47
#endif
dvander@2762
    48
dvander@2762
    49
#include "pcre_internal.h"
dvander@2762
    50
dvander@2762
    51
dvander@2762
    52
/*************************************************
dvander@2762
    53
*         Validate a UTF-8 string                *
dvander@2762
    54
*************************************************/
dvander@2762
    55
dvander@2762
    56
/* This function is called (optionally) at the start of compile or match, to
dvander@2762
    57
validate that a supposed UTF-8 string is actually valid. The early check means
dvander@2762
    58
that subsequent code can assume it is dealing with a valid string. The check
dvander@2762
    59
can be turned off for maximum performance, but the consequences of supplying
dvander@2762
    60
an invalid string are then undefined.
dvander@2762
    61
dvander@2762
    62
Originally, this function checked according to RFC 2279, allowing for values in
dvander@2762
    63
the range 0 to 0x7fffffff, up to 6 bytes long, but ensuring that they were in
dvander@2762
    64
the canonical format. Once somebody had pointed out RFC 3629 to me (it
dvander@2762
    65
obsoletes 2279), additional restrictions were applied. The values are now
dvander@2762
    66
limited to be between 0 and 0x0010ffff, no more than 4 bytes long, and the
dvander@2762
    67
subrange 0xd000 to 0xdfff is excluded.
dvander@2762
    68
dvander@2762
    69
Arguments:
dvander@2762
    70
  string       points to the string
dvander@2762
    71
  length       length of string, or -1 if the string is zero-terminated
dvander@2762
    72
dvander@2762
    73
Returns:       < 0    if the string is a valid UTF-8 string
dvander@2762
    74
               >= 0   otherwise; the value is the offset of the bad byte
dvander@2762
    75
*/
dvander@2762
    76
dvander@2762
    77
int
dvander@2762
    78
_pcre_valid_utf8(USPTR string, int length)
dvander@2762
    79
{
dvander@2762
    80
#ifdef SUPPORT_UTF8
dvander@2762
    81
register USPTR p;
dvander@2762
    82
dvander@2762
    83
if (length < 0)
dvander@2762
    84
  {
dvander@2762
    85
  for (p = string; *p != 0; p++);
dvander@2762
    86
  length = p - string;
dvander@2762
    87
  }
dvander@2762
    88
dvander@2762
    89
for (p = string; length-- > 0; p++)
dvander@2762
    90
  {
dvander@2762
    91
  register int ab;
dvander@2762
    92
  register int c = *p;
dvander@2762
    93
  if (c < 128) continue;
dvander@2762
    94
  if (c < 0xc0) return p - string;
dvander@2762
    95
  ab = _pcre_utf8_table4[c & 0x3f];     /* Number of additional bytes */
dvander@2762
    96
  if (length < ab || ab > 3) return p - string;
dvander@2762
    97
  length -= ab;
dvander@2762
    98
dvander@2762
    99
  /* Check top bits in the second byte */
dvander@2762
   100
  if ((*(++p) & 0xc0) != 0x80) return p - string;
dvander@2762
   101
dvander@2762
   102
  /* Check for overlong sequences for each different length, and for the
dvander@2762
   103
  excluded range 0xd000 to 0xdfff.  */
dvander@2762
   104
dvander@2762
   105
  switch (ab)
dvander@2762
   106
    {
dvander@2762
   107
    /* Check for xx00 000x (overlong sequence) */
dvander@2762
   108
dvander@2762
   109
    case 1:
dvander@2762
   110
    if ((c & 0x3e) == 0) return p - string;
dvander@2762
   111
    continue;   /* We know there aren't any more bytes to check */
dvander@2762
   112
dvander@2762
   113
    /* Check for 1110 0000, xx0x xxxx (overlong sequence) or
dvander@2762
   114
                 1110 1101, 1010 xxxx (0xd000 - 0xdfff) */
dvander@2762
   115
dvander@2762
   116
    case 2:
dvander@2762
   117
    if ((c == 0xe0 && (*p & 0x20) == 0) ||
dvander@2762
   118
        (c == 0xed && *p >= 0xa0))
dvander@2762
   119
      return p - string;
dvander@2762
   120
    break;
dvander@2762
   121
dvander@2762
   122
    /* Check for 1111 0000, xx00 xxxx (overlong sequence) or
dvander@2762
   123
       greater than 0x0010ffff (f4 8f bf bf) */
dvander@2762
   124
dvander@2762
   125
    case 3:
dvander@2762
   126
    if ((c == 0xf0 && (*p & 0x30) == 0) ||
dvander@2762
   127
        (c > 0xf4 ) ||
dvander@2762
   128
        (c == 0xf4 && *p > 0x8f))
dvander@2762
   129
      return p - string;
dvander@2762
   130
    break;
dvander@2762
   131
dvander@2762
   132
#if 0
dvander@2762
   133
    /* These cases can no longer occur, as we restrict to a maximum of four
dvander@2762
   134
    bytes nowadays. Leave the code here in case we ever want to add an option
dvander@2762
   135
    for longer sequences. */
dvander@2762
   136
dvander@2762
   137
    /* Check for 1111 1000, xx00 0xxx */
dvander@2762
   138
    case 4:
dvander@2762
   139
    if (c == 0xf8 && (*p & 0x38) == 0) return p - string;
dvander@2762
   140
    break;
dvander@2762
   141
dvander@2762
   142
    /* Check for leading 0xfe or 0xff, and then for 1111 1100, xx00 00xx */
dvander@2762
   143
    case 5:
dvander@2762
   144
    if (c == 0xfe || c == 0xff ||
dvander@2762
   145
       (c == 0xfc && (*p & 0x3c) == 0)) return p - string;
dvander@2762
   146
    break;
dvander@2762
   147
#endif
dvander@2762
   148
dvander@2762
   149
    }
dvander@2762
   150
dvander@2762
   151
  /* Check for valid bytes after the 2nd, if any; all must start 10 */
dvander@2762
   152
  while (--ab > 0)
dvander@2762
   153
    {
dvander@2762
   154
    if ((*(++p) & 0xc0) != 0x80) return p - string;
dvander@2762
   155
    }
dvander@2762
   156
  }
dvander@2762
   157
#else
dvander@2762
   158
(void)(string);  /* Keep picky compilers happy */
dvander@2762
   159
(void)(length);
dvander@2762
   160
#endif
dvander@2762
   161
dvander@2762
   162
return -1;
dvander@2762
   163
}
dvander@2762
   164
dvander@2762
   165
/* End of pcre_valid_utf8.c */