Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: Nikita Pettik <korablev@tarantool.org>
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH v2 10/10] iproto: support error stacked diagnostic area
Date: Thu, 2 Apr 2020 02:29:47 +0200	[thread overview]
Message-ID: <64be3c70-4ec9-0743-0b6d-e7453239db4a@tarantool.org> (raw)
In-Reply-To: <20200401222456.GA27659@tarantool.org>

Thanks for the fixes!

See 6 comments below.

> diff --git a/src/box/xrow.c b/src/box/xrow.c
> index 28adbdc1f..f33226dc5 100644
> --- a/src/box/xrow.c
> +++ b/src/box/xrow.c
> @@ -1070,19 +1083,62 @@ xrow_encode_auth(struct xrow_header *packet, const char *salt, size_t salt_len,
>  	return 0;
>  }
>  
> +static int
> +iproto_decode_error_stack(const char **pos)
> +{
> +	const char *reason = NULL;
> +	static_assert(TT_STATIC_BUF_LEN >= DIAG_ERRMSG_MAX, "static buffer is "\
> +		      "expected to be larger than error message max length");
> +	/*
> +	 * Erase previously set diag errors. It is required since
> +	 * box_error_add() does not replace previous errors.
> +	 */
> +	box_error_clear();
> +	assert(mp_typeof(**pos) == MP_ARRAY);

1. Better keep this check here instead of xrow_decode_error(). It looks
strange, when iproto_decode_error_stack() validates everything except
the top header, which is somewhy expected to be validated by the
caller.

> +	uint32_t stack_sz = mp_decode_array(pos);
> +	for (uint32_t i = 0; i < stack_sz; i++) {
> +		uint32_t code = 0;
> +		if (mp_typeof(**pos) != MP_MAP)
> +			return -1;
> +		uint32_t map_sz = mp_decode_map(pos);
> +		for (uint32_t key_idx = 0; key_idx < map_sz; key_idx++) {
> +			if (mp_typeof(**pos) != MP_UINT)
> +				return -1;
> +			uint8_t key = mp_decode_uint(pos);

2. If I will send value 0xffffff01, it will be considered valid.
Better save it into uint64_t, since mp_decode_uint() returns this
type. In that case all will be fine.

The same with code. Better get the code as uint64_t and compare
with UINT32_MAX. Because ClientError has uint32_t error code type.

> +			if (key == IPROTO_ERROR_CODE) {
> +				if (mp_typeof(**pos) != MP_UINT)
> +					return -1;
> +				code = mp_decode_uint(pos);
> +			} else if (key == IPROTO_ERROR_MESSAGE) {
> +				if (mp_typeof(**pos) != MP_STR)
> +					return -1;
> +				uint32_t len;
> +				const char *str = mp_decode_str(pos, &len);
> +				reason = tt_cstr(str, len);
> +			} else {
> +				mp_next(pos);
> +				continue;
> +			}
> +			box_error_add(__FILE__, __LINE__, code, reason);
> +		}
> +	}
> +	return 0;
> +}
> +
>  void
>  xrow_decode_error(struct xrow_header *row)
>  {
>  	uint32_t code = row->type & (IPROTO_TYPE_ERROR - 1);
>  
>  	char error[DIAG_ERRMSG_MAX] = { 0 };
> -	const char *pos;
> +	const char *pos, *end;
>  	uint32_t map_size;
>  
>  	if (row->bodycnt == 0)
>  		goto error;
>  	pos = (char *) row->body[0].iov_base;
> -	if (mp_check(&pos, pos + row->body[0].iov_len))
> +	end = pos + row->body[0].iov_len;
> +	if (mp_check(&pos, end))
>  		goto error;

3. This hunk is clearly an artifact from the old patch
version. Dropped it and nothing changed.

>  
>  	pos = (char *) row->body[0].iov_base;
> diff --git a/test/box/iproto.result b/test/box/iproto.result
> new file mode 100644
> index 000000000..b6dc7ed4c
> --- /dev/null
> +++ b/test/box/iproto.result
> @@ -0,0 +1,142 @@
> +---
> +...
> +-- gh-1148: test capabilities of stacked diagnostics bypassing net.box.
> +--
> +test_run:cmd("setopt delimiter ';'")
> +---
> +- true
> +...
> +stack_err = function()
> +    local e1 = box.error.new({code = 111, reason = "e1"})
> +    local e2 = box.error.new({code = 111, reason = "e2"})
> +    local e3 = box.error.new({code = 111, reason = "e3"})
> +    assert(e1 ~= nil)
> +    e2:set_prev(e1)
> +    assert(e2.prev == e1)
> +    e3:set_prev(e2)
> +    box.error(e3)
> +end;
> +---
> +...
> +test_run:cmd("setopt delimiter ''");
> +---
> +- true
> +...
> +box.schema.user.grant('guest', 'read, write, execute', 'universe')

4. Useful command, easy to remember:

    box.schema.user.grant/revoke('guest', 'super')

Is shorter, and has basically the same effect + a few more permissions.
In case you like me look for this 'grant' command in other test files to
copy paste it every time. Up to you what to use. JFYI.

> diff --git a/test/unit/xrow.cc b/test/unit/xrow.cc
> index 68a334239..954f22f16 100644
> --- a/test/unit/xrow.cc
> +++ b/test/unit/xrow.cc

5. This test crashes on travis and locally on my machine. Probably
a typo somewhere.

I also added a test for the uint64 vs uint8 result of mp_decode_uint().
See it below and pushed on top of the branch as a separate commit.

====================
diff --git a/test/unit/xrow.cc b/test/unit/xrow.cc
index 954f22f16..1449d49a5 100644
--- a/test/unit/xrow.cc
+++ b/test/unit/xrow.cc
@@ -255,7 +255,7 @@ error_stack_entry_encode(char *pos, const char *err_str)
 void
 test_xrow_error_stack_decode()
 {
-	plan(14);
+	plan(15);
 	char buffer[2048];
 	/*
 	 * To start with, let's test the simplest and obsolete
@@ -372,6 +372,24 @@ test_xrow_error_stack_decode()
 	isnt(last, NULL, "xrow_decode succeed: diag has been set");
 	is(strcmp(last->errmsg, ""), 0, "xrow_decode corrupted stack: "
 	   "stack's map wrong value type");
+
+	/* Bad key in the packet. */
+	diag_clear(diag_get());
+	pos = mp_encode_map(buffer, 1);
+	pos = mp_encode_uint(pos, IPROTO_ERROR_STACK);
+	pos = mp_encode_array(pos, 1);
+	pos = mp_encode_map(pos, 2);
+	pos = mp_encode_uint(pos, 0xff000000 | IPROTO_ERROR_CODE);
+	pos = mp_encode_uint(pos, 159);
+	pos = mp_encode_uint(pos, IPROTO_ERROR_MESSAGE);
+	pos = mp_encode_str(pos, "", 0);
+	header.body[0].iov_base = buffer;
+	header.body[0].iov_len = pos - buffer;
+	xrow_decode_error(&header);
+	ok(diag_is_empty(diag_get()),
+	   "xrow_decode failed: bad error object key");
+	last = diag_last_error(diag_get());
+
 	check_plan();
 }
 ====================

On 02/04/2020 00:24, Nikita Pettik wrote:
> On 01 Apr 16:26, Nikita Pettik wrote:
>> @@ -1169,7 +1166,7 @@ xrow_decode_error(struct xrow_header *row)
>>  		} else if (key == IPROTO_ERROR_STACK ) {
>>  			if (mp_check_array(pos, end) != 0)
>>  				goto error;
>> -			if (iproto_decode_error_stack(&pos, end) != 0)
>> +			if (iproto_decode_error_stack(&pos) != 0)
>>  				continue;
>>  		} else {
>>  			mp_next(&pos);
>>
>>> I don't see any tests on that. Are there some? Maybe at least
>>> unit tests, in xrow.cc? Although a proper test would try to
>>> send an error stack through applier. Because xrow_decode_error()
>>> is used only there.
>>
>> I'm a bit new to replication tests. I've been working on it.
>> Could you please review the rest of changes so far?

6. I tried to find how to send a stacked error to applier. This
should be done from relay. And seems like it is impossible to do
from relay. Simply because there are no any user defined code to
create stacked errors, and because internals of relay don't use
stacked errors so far. Probably an error injection could help to
create an artificial error, but I think the unit test should be
enough.

  reply	other threads:[~2020-04-02  0:29 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-25  1:42 [Tarantool-patches] [PATCH v2 00/10] Stacked diagnostics Nikita Pettik
2020-03-25  1:42 ` [Tarantool-patches] [PATCH v2 01/10] box: rfc for stacked diagnostic area Nikita Pettik
2020-03-25  8:27   ` Konstantin Osipov
2020-03-25 14:08     ` Nikita Pettik
2020-03-25  1:42 ` [Tarantool-patches] [PATCH v2 02/10] box: rename diag_add_error to diag_set_error Nikita Pettik
2020-03-25  8:27   ` Konstantin Osipov
2020-03-26  0:22   ` Vladislav Shpilevoy
2020-03-26 12:31     ` Nikita Pettik
2020-03-25  1:42 ` [Tarantool-patches] [PATCH v2 03/10] test: move box.error tests to box/error.test.lua Nikita Pettik
2020-03-25  8:28   ` Konstantin Osipov
2020-03-26  0:22   ` Vladislav Shpilevoy
2020-03-26 12:31     ` Nikita Pettik
2020-03-25  1:43 ` [Tarantool-patches] [PATCH v2 04/10] box/error: introduce box.error.set() method Nikita Pettik
2020-03-25  8:33   ` Konstantin Osipov
2020-03-25 17:41     ` Nikita Pettik
2020-03-26  0:22   ` Vladislav Shpilevoy
2020-03-26 12:31     ` Nikita Pettik
2020-03-25  1:43 ` [Tarantool-patches] [PATCH v2 05/10] box/error: don't set error created via box.error.new to diag Nikita Pettik
2020-03-26 16:50   ` Konstantin Osipov
2020-03-26 17:59     ` Nikita Pettik
2020-03-26 18:06       ` Nikita Pettik
2020-03-26 18:07       ` Alexander Turenko
2020-03-27  0:19   ` Vladislav Shpilevoy
2020-03-27 13:09     ` Nikita Pettik
2020-03-25  1:43 ` [Tarantool-patches] [PATCH v2 06/10] box: introduce stacked diagnostic area Nikita Pettik
2020-03-26 16:54   ` Konstantin Osipov
2020-03-26 18:03     ` Nikita Pettik
2020-03-26 18:08       ` Konstantin Osipov
2020-03-28 18:40   ` Vladislav Shpilevoy
2020-04-01 16:09     ` Nikita Pettik
2020-04-02  0:29       ` Vladislav Shpilevoy
2020-04-02 17:42         ` Nikita Pettik
2020-04-02 22:20           ` Vladislav Shpilevoy
2020-04-03  1:54             ` Nikita Pettik
2020-04-03 23:17               ` Vladislav Shpilevoy
2020-03-28 18:59   ` Vladislav Shpilevoy
2020-03-31 17:44     ` Nikita Pettik
2020-04-02  0:29       ` Vladislav Shpilevoy
2020-04-02 14:16         ` Nikita Pettik
2020-03-25  1:43 ` [Tarantool-patches] [PATCH v2 07/10] box: use stacked diagnostic area for functional indexes Nikita Pettik
2020-03-30 23:24   ` Vladislav Shpilevoy
2020-04-01 15:53     ` Nikita Pettik
2020-03-25  1:43 ` [Tarantool-patches] [PATCH v2 08/10] box/error: clarify purpose of reference counting in struct error Nikita Pettik
2020-03-30 23:24   ` Vladislav Shpilevoy
2020-03-25  1:43 ` [Tarantool-patches] [PATCH v2 09/10] iproto: refactor error encoding with mpstream Nikita Pettik
2020-03-30 23:24   ` Vladislav Shpilevoy
2020-04-01 15:54     ` Nikita Pettik
2020-03-25  1:43 ` [Tarantool-patches] [PATCH v2 10/10] iproto: support error stacked diagnostic area Nikita Pettik
2020-03-30 23:24   ` Vladislav Shpilevoy
2020-04-01 16:26     ` Nikita Pettik
2020-04-01 22:24       ` Nikita Pettik
2020-04-02  0:29         ` Vladislav Shpilevoy [this message]
2020-04-02 14:01           ` Nikita Pettik
2020-04-02 22:20             ` Vladislav Shpilevoy
2020-04-03  2:16               ` Nikita Pettik
2020-04-03 23:17                 ` Vladislav Shpilevoy
2020-04-06 11:07                   ` Nikita Pettik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=64be3c70-4ec9-0743-0b6d-e7453239db4a@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v2 10/10] iproto: support error stacked diagnostic area' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox