PHPIDX Open Blog

Informative blogs and opinions.

Using PHP ctype Functions

Something to be aware of when using any of the ctype_ functions. Unlike most PHP built-ins the ctype extension does not do an implicit cast to string, instead it has two behaviors:

If you pass in a string type it works as expected, iterates the string and calls the unix function “isdigit” for each character, returning false on the first non-digit.

But pass in an integer and it treats it as an single ASCII character, calling the “isdigit” function once. The ASCII range for numbers is 48-57 So, “ctype_digit(47) == false”, “ctype_digit(48) == true”, “ctype_digit(58) == false”. Further, if the number is between -128 and -1 it will add 256.

Anyway, something to be aware of. For safety sake you should cast any variables that might even potentially be a non-string to string when using the ctype_ functions.

For reference, here’s the C macro source, used in all ctype_ calls. “iswhat” expands to the unix function name. “isdigit” in this case.

/ext/ctype/ctype.c

#define CTYPE(iswhat) \
zval *c, tmp; \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “z”, &c) == FAILURE) \
return; \
if (Z_TYPE_P(c) == IS_LONG) { \
if (Z_LVAL_P(c) <= 255 && Z_LVAL_P(c) >= 0) { \
RETURN_BOOL(iswhat(Z_LVAL_P(c))); \
} else if (Z_LVAL_P(c) >= -128 && Z_LVAL_P(c) < 0) { \
RETURN_BOOL(iswhat(Z_LVAL_P(c) + 256)); \
} \
tmp = *c; \
zval_copy_ctor(&tmp); \
convert_to_string(&tmp); \
} else { \
tmp = *c; \
} \
if (Z_TYPE(tmp) == IS_STRING) { \
char *p = Z_STRVAL(tmp), *e = Z_STRVAL(tmp) + Z_STRLEN(tmp); \
if (e == p) { \
if (Z_TYPE_P(c) == IS_LONG) zval_dtor(&tmp); \
RETURN_FALSE; \
} \
while (p < e) { \
if(!iswhat((int)*(unsigned char *)(p++))) { \
if (Z_TYPE_P(c) == IS_LONG) zval_dtor(&tmp); \
RETURN_FALSE; \
} \
} \
if (Z_TYPE_P(c) == IS_LONG) zval_dtor(&tmp); \
RETURN_TRUE; \
} else { \
RETURN_FALSE; \
} \

/* }}} */

/* {{{ proto bool ctype_digit(mixed c)
Checks for numeric character(s) */
static PHP_FUNCTION(ctype_digit)
{
CTYPE(isdigit);
}
/* }}} */

Your Comment