Skip to content

Commit 4e92056

Browse files
committed
Optimized getBytesFromString
1 parent df6d85a commit 4e92056

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

ext/random/randomizer.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,6 @@ PHP_METHOD(Random_Randomizer, getBytesFromString)
388388

389389
zend_long user_length;
390390
zend_string *source, *retval;
391-
size_t total_size = 0;
392391

393392
ZEND_PARSE_PARAMETERS_START(2, 2);
394393
Z_PARAM_STR(source)
@@ -410,17 +409,21 @@ PHP_METHOD(Random_Randomizer, getBytesFromString)
410409

411410
size_t length = (size_t)user_length;
412411
retval = zend_string_alloc(length, 0);
412+
char *rptr = ZSTR_VAL(retval);
413+
char *sptr = ZSTR_VAL(source);
413414

415+
size_t to_read = length;
414416
if (max_offset > 0xff) {
415-
while (total_size < length) {
417+
while (to_read > 0) {
416418
uint64_t offset = engine.algo->range(engine.state, 0, max_offset);
417419

418420
if (EG(exception)) {
419421
zend_string_free(retval);
420422
RETURN_THROWS();
421423
}
422424

423-
ZSTR_VAL(retval)[total_size++] = ZSTR_VAL(source)[offset];
425+
*rptr++ = sptr[offset];
426+
to_read--;
424427
}
425428
} else {
426429
uint64_t mask = max_offset;
@@ -432,31 +435,38 @@ PHP_METHOD(Random_Randomizer, getBytesFromString)
432435
mask |= mask >> 2;
433436
mask |= mask >> 4;
434437

438+
/* Example: if mask is 0xAB, will be 0xABABABABABABABAB */
439+
uint64_t mask_repeat = (~((uint64_t) 0) / 0xFF) * mask;
435440
int failures = 0;
436-
while (total_size < length) {
441+
while (to_read > 0) {
437442
php_random_result result = engine.algo->generate(engine.state);
438443
if (EG(exception)) {
439444
zend_string_free(retval);
440445
RETURN_THROWS();
441446
}
442447

443-
for (size_t i = 0; i < result.size; i++) {
444-
uint64_t offset = (result.result >> (i * 8)) & mask;
445-
448+
uint64_t offsets = result.result & mask_repeat;
449+
size_t ret_size = result.size;
450+
while (ret_size > 0) {
451+
ret_size--;
452+
uint64_t offset = offsets & 0xff;
453+
offsets >>= 8;
446454
if (offset > max_offset) {
447-
if (++failures > PHP_RANDOM_RANGE_ATTEMPTS) {
455+
if (failures == PHP_RANDOM_RANGE_ATTEMPTS) {
448456
zend_string_free(retval);
449457
zend_throw_error(random_ce_Random_BrokenRandomEngineError, "Failed to generate an acceptable random number in %d attempts", PHP_RANDOM_RANGE_ATTEMPTS);
450458
RETURN_THROWS();
459+
} else {
460+
failures++;
461+
continue;
451462
}
452-
453-
continue;
454463
}
455464

456465
failures = 0;
457466

458-
ZSTR_VAL(retval)[total_size++] = ZSTR_VAL(source)[offset];
459-
if (total_size >= length) {
467+
*rptr++ = sptr[offset];
468+
to_read--;
469+
if (to_read == 0) {
460470
break;
461471
}
462472
}

0 commit comments

Comments
 (0)