Skip to content

Commit b493ca9

Browse files
committed
#58 - fixed
1 parent 2152db2 commit b493ca9

File tree

6 files changed

+80
-48
lines changed

6 files changed

+80
-48
lines changed

src/ngx_http_tnt_handlers.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,15 @@ ngx_http_tnt_get_output_size(
4747
(void)ctx;
4848
size_t output_size = ngx_http_tnt_overhead();
4949

50-
if (r->method & NGX_HTTP_POST ||
51-
((r->method & NGX_HTTP_PUT || r->method & NGX_HTTP_DELETE)
52-
&& r->headers_in.content_length_n > 0))
53-
{
50+
if (r->headers_in.content_length_n > 0) {
5451
output_size += r->headers_in.content_length_n;
5552
}
5653

5754
if (tlcf->method.len) {
5855
output_size += tlcf->method.len;
5956
}
6057

61-
output_size *= tlcf->in_multiplier;
58+
output_size *= tlcf->in_multiplier + 20 /* header overhead */;
6259

6360
if (request_b != NULL) {
6461
output_size += request_b->last - request_b->start;

src/tp_transcode.c

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ typedef struct {
153153
bool transcode_first_enter;
154154
} yajl_ctx_t;
155155

156-
157156
static inline bool
158157
stack_push(yajl_ctx_t *s, char *ptr, int mask)
159158
{
@@ -217,6 +216,19 @@ stack_grow(yajl_ctx_t *s, int cond)
217216
#define stack_grow_array(s) stack_grow((s), TYPE_ARRAY)
218217
#define stack_grow_map(s) stack_grow((s), TYPE_MAP)
219218

219+
static inline bool
220+
bind_data(yajl_ctx_t *s_ctx)
221+
{
222+
tp_transcode_t *tc = s_ctx->tc;
223+
if (tc->data.pos && tc->data.len) {
224+
if (s_ctx->tp.e - s_ctx->tp.p < (ptrdiff_t)tc->data.len)
225+
return false;
226+
memcpy(s_ctx->tp.p, tc->data.pos, tc->data.len);
227+
tp_add(&s_ctx->tp, tc->data.len);
228+
}
229+
return true;
230+
}
231+
220232
static int
221233
yajl_null(void *ctx)
222234
{
@@ -357,6 +369,7 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
357369
if (unlikely(s_ctx->tc->batch_size > MAX_BATCH_SIZE)) {
358370

359371
/* TODO '16384' -> MAX_BATCH_SIZE
372+
* Is this okay?
360373
*/
361374
say_error(s_ctx, -32600,
362375
"too large batch, max allowed 16384 calls per request");
@@ -366,6 +379,8 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
366379
if (unlikely(!tp_call_wof(&s_ctx->tp)))
367380
say_overflow_r_2(s_ctx);
368381

382+
/** Set method binded to this transcoding
383+
*/
369384
if (!s_ctx->read_method) {
370385
tp_transcode_t *tc = s_ctx->tc;
371386
if (unlikely(!tp_call_wof_add_func(&s_ctx->tp,
@@ -387,7 +402,9 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
387402
say_overflow_r_2(s_ctx);
388403

389404
} else if (s_ctx->stage == WAIT_NEXT) {
390-
405+
/**
406+
* {"params": []}
407+
*/
391408
if (len == sizeof("params") - 1
392409
&& key[0] == 'p'
393410
&& key[1] == 'a'
@@ -397,10 +414,8 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
397414
&& key[5] == 's')
398415
{
399416
dd("PARAMS STAGE\n");
400-
401417
if (unlikely(!tp_call_wof_add_params(&s_ctx->tp)))
402418
say_overflow_r_2(s_ctx);
403-
404419
s_ctx->stage = PARAMS;
405420
}
406421
else if (len == sizeof("id") - 1
@@ -410,6 +425,9 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
410425
dd("ID STAGE\n");
411426
s_ctx->stage = ID;
412427
}
428+
/* {"method": STR}*
429+
*
430+
*/
413431
else if (s_ctx->read_method
414432
&& len == sizeof("method") - 1
415433
&& key[0] == 'm'
@@ -444,6 +462,7 @@ yajl_start_map(void *ctx)
444462

445463
bool r = false;
446464
if (unlikely(s_ctx->size == 0))
465+
/**/
447466
r = stack_push(s_ctx, s_ctx->tp.p, TYPE_MAP | PARAMS);
448467
else
449468
r = stack_push(s_ctx, s_ctx->tp.p, TYPE_MAP);
@@ -467,19 +486,21 @@ yajl_end_map(void *ctx)
467486
{
468487
yajl_ctx_t *s_ctx = (yajl_ctx_t *)ctx;
469488

470-
/** Say we already read method. Otherwise we'll have an error.
471-
* E.g. proto await for "params", "id" and "method".
472-
*/
473-
if (!s_ctx->read_method
474-
&& (s_ctx->been_stages & (PARAMS | ID))
475-
== (PARAMS | ID))
476-
{
477-
s_ctx->been_stages |= METHOD;
478-
}
489+
if (s_ctx->size == 0) {
490+
491+
if (unlikely(!tp_call_wof_add_params(&s_ctx->tp)))
492+
say_overflow_r_2(s_ctx);
493+
494+
if (!(s_ctx->been_stages & PARAMS)) {
495+
496+
if (s_ctx->tc->data.pos && s_ctx->tc->data.len) {
497+
tp_encode_array(&s_ctx->tp, 1);
498+
if (unlikely(!bind_data(s_ctx)))
499+
say_overflow_r_2(s_ctx);
500+
} else
501+
tp_encode_array(&s_ctx->tp, 0);
502+
}
479503

480-
if ((s_ctx->been_stages & (PARAMS | ID | METHOD))
481-
== (PARAMS | ID | METHOD))
482-
{
483504
dd("WAIT NEXT BATCH\n");
484505
s_ctx->stage = INIT;
485506
s_ctx->been_stages = 0;
@@ -509,12 +530,13 @@ yajl_end_map(void *ctx)
509530
return 1;
510531
}
511532

533+
512534
static int
513535
yajl_start_array(void *ctx)
514536
{
515537
yajl_ctx_t *s_ctx = (yajl_ctx_t *)ctx;
516538

517-
if (unlikely(s_ctx->stage == INIT)) {
539+
if (s_ctx->stage == INIT) {
518540
s_ctx->batch_mode_on = true;
519541
return 1;
520542
}
@@ -526,33 +548,27 @@ yajl_start_array(void *ctx)
526548

527549
stack_grow_array(s_ctx);
528550

529-
bool r = false, is_params = false;
551+
bool push_ok = false, bind_first_argument = true;
530552
if (unlikely(s_ctx->size == 0)) {
531-
r = stack_push(s_ctx, s_ctx->tp.p, TYPE_ARRAY | PARAMS);
532-
is_params = true;
533-
}
534-
else
535-
r = stack_push(s_ctx, s_ctx->tp.p, TYPE_ARRAY);
553+
push_ok = stack_push(s_ctx, s_ctx->tp.p, TYPE_ARRAY | PARAMS);
554+
bind_first_argument = true;
555+
} else
556+
push_ok = stack_push(s_ctx, s_ctx->tp.p, TYPE_ARRAY);
536557

537-
if (unlikely(!r)) {
558+
if (unlikely(!push_ok)) {
538559
say_error(s_ctx, -32603, "[BUG?] 'stack' overflow");
539560
return 0;
540561
}
541562

542-
if (unlikely(s_ctx->tp.e < s_ctx->tp.p + 1 + sizeof(uint32_t)))
563+
if (unlikely(s_ctx->tp.e < (s_ctx->tp.p + 1 + sizeof(uint32_t))))
543564
say_overflow_r_2(s_ctx);
544565

545566
tp_add(&s_ctx->tp, 1 + sizeof(uint32_t));
546567

547-
// Bind data here [
548-
if (unlikely(is_params)) {
549-
tp_transcode_t *tc = s_ctx->tc;
550-
if (tc->data.pos && tc->data.len) {
551-
if (s_ctx->tp.e - s_ctx->tp.p < (ptrdiff_t)tc->data.len)
568+
// Binding data [
569+
if (unlikely(bind_first_argument)) {
570+
if (!bind_data(s_ctx))
552571
say_overflow_r_2(s_ctx);
553-
memcpy(s_ctx->tp.p, tc->data.pos, tc->data.len);
554-
tp_add(&s_ctx->tp, tc->data.len);
555-
}
556572
}
557573
// ]
558574

@@ -705,14 +721,8 @@ yajl_json2tp_transcode(void *ctx, const char *input, size_t input_size)
705721
* So! PWN this via bool flag and some checks
706722
*
707723
* NOTE
708-
* 1. Check len(buffer) is wrong.
724+
* Check len(buffer) is wrong.
709725
* We may have a very large buffer which passed to this function by 1-byte.
710-
*
711-
* 2. If we'll have buffer which passed to this function by 1-byte then
712-
* those checks will pwn my transcoder! Wooo! Any suggestions?
713-
*
714-
*
715-
* 3. Pwn == 'invalid json'
716726
*/
717727
if (unlikely(!s_ctx->transcode_first_enter)) {
718728
s_ctx->transcode_first_enter = true;
@@ -758,15 +768,19 @@ yajl_json2tp_complete(void *ctx, size_t *complete_msg_size)
758768
yajl_ctx_t *s_ctx = (yajl_ctx_t *)ctx;
759769

760770
const yajl_status stat = yajl_complete_parse(s_ctx->hand);
771+
772+
/* OK */
761773
if (likely(stat == yajl_status_ok)) {
762774
*complete_msg_size = tp_used(&s_ctx->tp);
763775
return TP_TRANSCODE_OK;
764776
}
765777

778+
/* An error w/o message */
766779
if (s_ctx->tc->errmsg == NULL) {
767780
say_invalid_json(s_ctx);
768781
}
769782

783+
/* ? */
770784
return TP_TRANSCODE_ERROR;
771785
}
772786

test/http_utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#VERBOSE = True
1212
VERBOSE = False
13-
BASE_URL = 'http://127.0.0.1:8081'
13+
BASE_URL = 'http://0.0.0.0:8081'
1414

1515

1616
def post(url, data, headers):
@@ -79,6 +79,9 @@ def request_raw(url, data, headers):
7979
print(traceback.format_exc())
8080
return (False, e)
8181

82+
def request(url, data, headers = None):
83+
return request_raw(url, json.dumps(data), headers)
84+
8285
def put(url, data, headers):
8386
out = '{}'
8487
try:
@@ -240,6 +243,7 @@ def delete_success(url, data, headers):
240243
(code, msg) = delete(url, data, headers)
241244
assert(code == 200), 'expected 200'
242245
result = get_result(msg)
246+
return result
243247

244248
def assert_headers(result, headers_in):
245249
for header in headers_in:

test/ngx_confs/tnt_server_test.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ http {
165165
}
166166
tnt_http_rest_methods get delete;
167167
tnt_http_methods all;
168-
tnt_pure_result off;
169168
tnt_pass_http_request on parse_args;
170169
tnt_pass tnt;
171170
}

test/test.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ function delete(request, a1, a2)
103103
end
104104

105105
function insert(request, a1, a2)
106-
return request, a1, a2
106+
return request
107+
end
108+
109+
function update(request)
110+
return request
107111
end
108112
-- ]]

test/v23_features.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,17 @@
136136
delete_success(preset_method_location, None, None)
137137
delete_success(preset_method_location, {'params':[1, 2]}, None)
138138

139+
#===========
140+
#
141+
print('[+] issue #58, RPC w/o params')
142+
143+
preset_method_location = BASE_URL + '/issue_58'
144+
put_success(preset_method_location, {'id':1}, None)
145+
delete_success(preset_method_location, {'params':[]}, None)
146+
result = delete_success(preset_method_location, None, None)
147+
148+
preset_method_location = BASE_URL + '/issue_58'
149+
150+
(rc, result) = request(preset_method_location, [{'id': 1}, {'id': 2}])
151+
assert(result[0]['id'] == 1), 'expected id = 1'
152+
assert(result[1]['id'] == 2), 'expected id = 2'

0 commit comments

Comments
 (0)