2015-08-12 2 views
1

Я просматривал исходный код SQLite, когда я натолкнулся на эту функцию, начиная с строки 387 в shell.c.Границы указателя и арифметика указателя в исходном коде SQLite

Исходный код: https://www.sqlite.org/download.html

Функция в вопросе:

/* 
** Determines if a string is a number of not. 
*/ 
static int isNumber(const char *z, int *realnum){ 
    if(*z=='-' || *z=='+') z++; 
    if(!IsDigit(*z)){ 
    return 0; 
    } 
    z++; 
    if(realnum) *realnum = 0; 
    while(IsDigit(*z)){ z++; } 
    if(*z=='.'){ 
    z++; 
    if(!IsDigit(*z)) return 0; 
    while(IsDigit(*z)){ z++; } 
    if(realnum) *realnum = 1; 
    } 
    if(*z=='e' || *z=='E'){ 
    z++; 
    if(*z=='+' || *z=='-') z++; 
    if(!IsDigit(*z)) return 0; 
    while(IsDigit(*z)){ z++; } 
    if(realnum) *realnum = 1; 
    } 
    return *z==0; 
} 

Примечание: IsDigit макрос, который подает неподписанный символ в isdigit, определенной в CType.

#define IsDigit(X) isdigit((unsigned char)X) 

Функция и использование указателя имеет смысл для меня, однако, первые две строки заставляет меня полагать, что они могут быть использованы ненадлежащим образом на основе моего понимания.

Они используют арифметику указателя для перемешивания по строке.

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

Если символ в первой позиции указателя является «-» или «+», переместите указатель на одну позиции. Однако это, похоже, не учитывает, если строка, переданная в функцию, имеет только один символ, который является символом «-» или «+».

if(!IsDigit(*z)){ 

Когда «г» разыменовывается, не это повреждено/незаконный доступ к памяти, потому что она выходит из рамки указателя, или есть что-то за кулисами с арифметикой указателей, что останавливает это происходило?

+0

SQLite используется на * сотнях миллионов * iOS и Android-устройствах каждый день. Скорее всего, вы не обнаружили ранее не обнаруженную ошибку при их основном анализе чисел. –

ответ

1

Нет, строки C, как ожидается, будут оканчиваться на нуль.

Если передать строку, содержащую только - или + символ, z указатель будет указывать на нулевой символ после того, как увеличивается и IsDigit(*z) будет эквивалентна IsDigit(0), которая будет вычисляться false и вернуть 0.

+0

Это имеет смысл, но «IsDigit (0)» будет оценивать значение «true», потому что 0 определяется как цифра. –

+0

Нет, * символ * ''0'' (числовое значение 48 в ASCII) будет распознаваться как цифра. Конечный NUL (числовое значение 0) не будет. –