데이터 형식 - 문자열
3922 단어 PHP 7 소스 일기 읽 기
Zend_string 데이터 구조
typedef struct _zend_string zend_string;
struct _zend_string {
zend_refcounted_h gc;
zend_ulong h; /* hash value */
size_t len;
char val[1];
};
이 구 조 는 네 명의 구성원 이 있다.
//file zend_string.c
static zend_always_inline zend_string *zend_string_alloc(size_t len, int persistent)
{
zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
....
//
zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(XtOffsetOf(zend_string, val) + len + 1), persistent); // 1 c \0
}
문자열 의 바 이 너 리 보안
C 언어 를 배 운 사람 은 알 아야 한다. 문자열 에 마지막 문 자 를 제외 하고
\0
가 포함 되 어 있 으 면 안 된다. 그렇지 않 으 면 문자열 의 끝 문자 로 여 겨 지기 때문에 C 언어의 문자열 에 많은 제한 이 있다. 예 를 들 어 그림, 파일 등 바 이 너 리 데 이 터 를 저장 하지 않 는 다.그러나 PHP 는 이러한 제한 이 없습니다. 문자열 은 바 이 너 리 데 이 터 를 저장 할 수 있 고 오류 가 발생 하지 않 습 니 다. PHP 의 이러한 능력 을 문자열 의 바 이 너 리 보안 이 라 고 합 니 다.C 코드:
char a[] = "aaa\0b";
int len = strlen(a);
printf("%d
", len); // 3
PHP 코드:
$a = "aaa\0b";
echo strlen($a).PHP_EOL; //5
급속 충전기 ~: 그런데 PHP 는 C 언어 로 쓰 여 있 지 않 나 요?왜 PHP 가 틀 리 지 않 습 니까?다시 한 번 zendstring 구조 체, 멤버 변수 len 기억 나 세 요?이것 은 바 이 너 리 보안 을 실현 하 는 관건 입 니 다. 우 리 는 C 처럼
\0
문자열 이 읽 혔 는 지 여 부 를 판단 하지 않 고 길이 len 을 통 해 문자열 의 바 이 너 리 안전 을 보장 합 니 다.//file : zend_string.h
static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size_t len)
{
register zend_ulong hash = Z_UL(5381);
/* variant with the hash unrolled eight times */
for (; len >= 8; len -= 8) {
hash = ((hash << 5) + hash) + *str++;
hash = ((hash << 5) + hash) + *str++;
hash = ((hash << 5) + hash) + *str++;
hash = ((hash << 5) + hash) + *str++;
hash = ((hash << 5) + hash) + *str++;
hash = ((hash << 5) + hash) + *str++;
hash = ((hash << 5) + hash) + *str++;
hash = ((hash << 5) + hash) + *str++;
}
switch (len) {
case 7: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
case 6: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
case 5: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
case 4: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
case 3: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
case 2: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
case 1: hash = ((hash << 5) + hash) + *str++; break;
case 0: break;
EMPTY_SWITCH_DEFAULT_CASE()
}
/* Hash value can't be zero, so we always set the high bit */
#if SIZEOF_ZEND_LONG == 8
return hash | Z_UL(0x8000000000000000);
#elif SIZEOF_ZEND_LONG == 4
return hash | Z_UL(0x80000000);
#else
# error "Unknown SIZEOF_ZEND_LONG"
#endif
}
를 붙 였 습 니 다.