wireshark/wsutil/ws_assert.h

88 lines
2.8 KiB
C
Raw Normal View History

/** @file
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __WS_ASSERT_H__
#define __WS_ASSERT_H__
#include <ws_symbol_export.h>
#include <ws_attributes.h>
#include <stdbool.h>
dfilter: Require double-quoted strings with "matches" Matches is a special case that looks on the RHS and tries to convert every unparsed value to a string, regardless of the LHS type. This is not how types work in the display filter. Require double-quotes to avoid ambiguity, because matches doesn't follow normal Wireshark display filter type rules. It doesn't need nor benefit from the flexibility provided by unparsed strings in the syntax. For matches the RHS is always a literal strings except if the RHS is also a field name, then it complains of an incompatible type. This is confusing. No type can be compatible because no type rules are ever considered. Every unparsed value is a text string except if it happens to coincide with a field name it also requires double-quoting or it throws a syntax error, just to be difficult. We could remove this odd quirk but requiring double-quotes for regular expressions is a better, more elegant fix. Before: Filter: tcp matches "udp" Constants: 00000 PUT_PCRE udp -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN Filter: tcp matches udp Constants: 00000 PUT_PCRE udp -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN Filter: tcp matches udp.srcport dftest: tcp and udp.srcport are not of compatible types. Filter: tcp matches udp.srcportt Constants: 00000 PUT_PCRE udp.srcportt -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN After: Filter: tcp matches "udp" Constants: 00000 PUT_PCRE udp -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN Filter: tcp matches udp dftest: "udp" was unexpected in this context. Filter: tcp matches udp.srcport dftest: "udp.srcport" was unexpected in this context. Filter: tcp matches udp.srcportt dftest: "udp.srcportt" was unexpected in this context. The error message could still be improved.
2021-10-09 15:40:08 +00:00
#include <string.h>
#ifdef WS_LOG_DOMAIN
#define _ASSERT_DOMAIN WS_LOG_DOMAIN
#else
#define _ASSERT_DOMAIN ""
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
WS_DLL_PUBLIC
WS_NORETURN
void ws_assert_failed(const char *file, int line, const char *function,
const char *domain, const char *assertion,
bool unreachable);
#define _ASSERT_FAIL(expr) \
ws_assert_failed(__FILE__, __LINE__, __func__, \
_ASSERT_DOMAIN, #expr, false)
/*
* ws_abort_if_fail() is not conditional on WS_DISABLE_ASSERT.
* Usually used to appease a static analyzer.
*/
#define ws_abort_if_fail(expr) \
do { if (!(expr)) _ASSERT_FAIL(expr); } while (0)
#ifdef WS_DISABLE_ASSERT
/*
* ws_assert() cannot produce side effects, otherwise code will
* behave differently because of WS_DISABLE_ASSERT, and probably introduce
* some difficult to track bugs.
*
* We don't want to execute the expression with WS_DISABLE_ASSERT because
* it might be time and space costly and the goal here is to optimize for
* WS_DISABLE_ASSERT. However removing it completely is not good enough
* because it might generate many unused variable warnings. So we use
* if (false) and let the compiler optimize away the dead execution branch.
*/
#define ws_assert(expr) do { if (false) ws_abort_if_fail(expr); } while (0)
#else
#define ws_assert(expr) ws_abort_if_fail(expr)
#endif
dfilter: Require double-quoted strings with "matches" Matches is a special case that looks on the RHS and tries to convert every unparsed value to a string, regardless of the LHS type. This is not how types work in the display filter. Require double-quotes to avoid ambiguity, because matches doesn't follow normal Wireshark display filter type rules. It doesn't need nor benefit from the flexibility provided by unparsed strings in the syntax. For matches the RHS is always a literal strings except if the RHS is also a field name, then it complains of an incompatible type. This is confusing. No type can be compatible because no type rules are ever considered. Every unparsed value is a text string except if it happens to coincide with a field name it also requires double-quoting or it throws a syntax error, just to be difficult. We could remove this odd quirk but requiring double-quotes for regular expressions is a better, more elegant fix. Before: Filter: tcp matches "udp" Constants: 00000 PUT_PCRE udp -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN Filter: tcp matches udp Constants: 00000 PUT_PCRE udp -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN Filter: tcp matches udp.srcport dftest: tcp and udp.srcport are not of compatible types. Filter: tcp matches udp.srcportt Constants: 00000 PUT_PCRE udp.srcportt -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN After: Filter: tcp matches "udp" Constants: 00000 PUT_PCRE udp -> reg#1 Instructions: 00000 READ_TREE tcp -> reg#0 00001 IF-FALSE-GOTO 3 00002 ANY_MATCHES reg#0 matches reg#1 00003 RETURN Filter: tcp matches udp dftest: "udp" was unexpected in this context. Filter: tcp matches udp.srcport dftest: "udp.srcport" was unexpected in this context. Filter: tcp matches udp.srcportt dftest: "udp.srcportt" was unexpected in this context. The error message could still be improved.
2021-10-09 15:40:08 +00:00
#define ws_assert_streq(s1, s2) \
ws_assert((s1) && (s2) && strcmp((s1), (s2)) == 0)
/*
* We don't want to disable ws_assert_not_reached() with WS_DISABLE_ASSERT.
* That would blast compiler warnings everywhere for no benefit, not
* even a miniscule performance gain. Reaching this function is always
* a programming error and will unconditionally abort execution.
*
* Note: With g_assert_not_reached() if the compiler supports unreachable
* built-ins (which recent versions of GCC and MSVC do) there is no warning
* blast with g_assert_not_reached() and G_DISABLE_ASSERT. However if that
* is not the case then g_assert_not_reached() is simply (void)0 and that
* causes the spurious warnings, because the compiler can't tell anymore
* that a certain code path is not used. We avoid that with
* ws_assert_not_reached(). There is no reason to ever use a no-op here.
*/
#define ws_assert_not_reached() \
ws_assert_failed(__FILE__, __LINE__, __func__, \
_ASSERT_DOMAIN, NULL, true)
#ifdef __cplusplus
}
#endif /* __cplusplus */
2021-05-20 01:54:35 +00:00
#endif /* __WS_ASSERT_H__ */