Skip to content

Commit 0effba7

Browse files
authored
Merge pull request #8 from ttys3/dict-sorted-by-keys
fix src/bdict.cc: dict keys should be sorted before encode
2 parents e6b7cd0 + 20d4451 commit 0effba7

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

src/bdict.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "blist.h"
55
#include "bstr.h"
66
#include "zend_container.h"
7+
#include "zend_sort.h"
78
#include <string>
89

910
bdict::bdict()
@@ -241,6 +242,11 @@ zval bdict::parse(const std::string &ben, size_t &pt)
241242
std::string bdict::encode() const
242243
{
243244
std::string result = "d";
245+
246+
// according to BEP http://bittorrent.org/beps/bep_0003.html
247+
// keys must be strings and appear in sorted order (sorted as raw strings, not alphanumerics).
248+
zend_hash_sort_ex(_data, zend_sort, php_array_key_compare_string, 0);
249+
244250
for (zend_hash_internal_pointer_reset(_data);
245251
zend_hash_has_more_elements(_data) == SUCCESS;
246252
zend_hash_move_forward(_data)) {

src/zend_container.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,33 @@
33

44
extern "C" {
55
#include "php.h"
6+
7+
// c func borrowed from https://github.com/php/php-src/blob/e08ce4c13db6e9aecd3497cd270b72d06c649bc7/ext/standard/array.c#L245
8+
static int php_array_key_compare_string(const void *a, const void *b)
9+
{
10+
Bucket *f = (Bucket *)a;
11+
Bucket *s = (Bucket *)b;
12+
const char *s1, *s2;
13+
size_t l1, l2;
14+
char buf1[MAX_LENGTH_OF_LONG + 1];
15+
char buf2[MAX_LENGTH_OF_LONG + 1];
16+
17+
if (f->key) {
18+
s1 = f->key->val;
19+
l1 = f->key->len;
20+
} else {
21+
s1 = zend_print_long_to_buf(buf1 + sizeof(buf1) - 1, f->h);
22+
l1 = buf1 + sizeof(buf1) - 1 - s1;
23+
}
24+
if (s->key) {
25+
s2 = s->key->val;
26+
l2 = s->key->len;
27+
} else {
28+
s2 = zend_print_long_to_buf(buf2 + sizeof(buf2) - 1, s->h);
29+
l2 = buf2 + sizeof(buf2) - 1 - s2;
30+
}
31+
return zend_binary_strcmp(s1, l1, s2, l2);
32+
}
633
}
734

835
#include "bdict.h"

tests/dict_ordered_keys.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
PHP Bencode - Dictionary Ordered Keys Test
3+
--FILE--
4+
<?php
5+
error_reporting(E_ALL);
6+
7+
$unordered_encoded = 'd7:ttg_tag32:8032a74ec22927a5bd6367537eafd87e7:privatei1e6:source20:[ttys3.bencode.test]e';
8+
9+
$bdict = bitem::parse($unordered_encoded);
10+
echo $bdict;
11+
12+
exit(0);
13+
?>
14+
--EXPECTF--
15+
d7:privatei1e6:source20:[ttys3.bencode.test]7:ttg_tag32:8032a74ec22927a5bd6367537eafd87ee

0 commit comments

Comments
 (0)