Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fail_if broken with check 0.15.1 #293

Closed
buscher opened this issue Jul 25, 2020 · 9 comments
Closed

fail_if broken with check 0.15.1 #293

buscher opened this issue Jul 25, 2020 · 9 comments

Comments

@buscher
Copy link

buscher commented Jul 25, 2020

fail_if is broken with check-0.15.1 (did not test 0.15.0)

The following code no longer compiles

#include <check.h>

void test_check0151()
{
    int a = 1, b = 2;
    fail_if(a == b);
}

with the output

test_check0151.c: In function 'test_check0151':
test_check0151.c:8:5: error: too few arguments to function '_ck_assert_failed'
    8 |     fail_if(a == b);
      |     ^~~~~~~
/usr/include/check.h:502:27: note: declared here
  502 | CK_DLL_EXP void CK_EXPORT _ck_assert_failed(const char *file, int line,
      |                           ^~~~~~~~~~~~~~~~~

I know fail_if is deprecated like forever... but old code is still using it :/

@brarcher
Copy link
Contributor

Ah, I see. This was probably broken in 0.15.0 as well. Check has a test for fail_if and passes a NULL as a second argument. There is a comment around there as to why::

/* taking out the NULL provokes an ISO C99 warning in GCC */

The changes in 0.15.0 enabled the checking of the printf style arguments, and in doing so likely now points out when no arguments are provided, such as with fail_if(a == b).

The documentation on the deprecated fail_if mention:

(Deprecated) Fails test if supplied condition evaluates to true and
displays user provided message.

The intent appears to be to have callers pass in a message, rather than making it optional. Up to 0.15.0 it was not enforced, and now a missing message is being pointed out.

I tried adding something like this:

#define fail_if(expr) fail_if(expr, NULL)

to see if it could be worked around, but this re-defines the macro rather than provides an alternative, so it will not work.

There are a few ways to solve this:

  1. Uses of fail_if() that have no message are given a NULL message (requires client code to change)
  2. Printf style warnings introduced in 0.15.0 are removed

I'd rather not remove the new warnings as they will help code use the correct printf arguments for Check's APIs. Do you have some other suggestions that may work?

@mandree
Copy link

mandree commented Jul 26, 2020

I'll prove "regression after 0.15.0 before 0.15.1" below, on FreeBSD ports and Git. I've tried building openvpn-auth-ldap, which is old code, and uses fail_() macros - and fail_() macros fail to compile with 0.15.1 due to one missing argument, but compiling the same source with 0.15.0 just fine.

I have also bisected this, and it got broken in 7ac1fcb and it doesn't look too surprising looking at the change.

$ git bisect bad
7ac1fcbcefe8813e2a75388ec61e20a184ddc8c8 is the first bad commit
commit 7ac1fcbcefe8813e2a75388ec61e20a184ddc8c8
Author: Jerry James <loganjerry@gmail.com>
Date:   Mon Jun 22 15:59:44 2020 -0600

    Make CK_ATTRIBUTE_FORMAT refer to the right arguments.

 src/check.c    | 12 +++++-------
 src/check.h.in | 13 +++++++------
 2 files changed, 12 insertions(+), 13 deletions(-)

uqs pushed a commit to freebsd/freebsd-ports that referenced this issue Jul 26, 2020
The option is a linker option but is passed to cc verbatim, and this
causes fallout complaints on head i386 (13):

--- lemon ---
cc  -o lemon lemon.o  -export-dynamic
ld: warning: cannot find entry symbol xport-dynamic; defaulting to 0x4049B0
===> making all in src
--- all ---
--- auth-ldap.o ---
cc -fPIC  -O2 -pipe  -fPIC -fstack-protector-strong -DLDAP_DEPRECATED -fno-strict-aliasing  -Wno-import -L/usr/local/lib -I/usr/local/include -fPIC -I/usr/local/include  -D_THREAD_SAFE  -fobjc-exceptions -fno-strict-aliasing -O2 -pipe  -fPIC -fstack-protector-strong -DLDAP_DEPRECATED -fno-strict-aliasing  -DHAVE_CONFIG_H -Wall -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -c auth-ldap.m -o auth-ldap.o -I. -I../src -I.. -I../src -I. -I../tests -I../tests
--- TRConfigParser.m ---
./tools/lemon -T../tools/lempar.c -m -q TRConfigParser.lemon -OTRConfigParser.m
Segmentation fault (core dumped)
*** [TRConfigParser.m] Error code 139

NOTE! With devel/check exactly at 0.15.1, this fails to build due to a regression
in check 0.15.1. 0.15.0 is fine, and the bug is reported here:

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=248274 (FreeBSD)
libcheck/check#293 (upstream)

http://beefy17.nyi.freebsd.org/data/head-i386-default/p543393_s363499/logs/openvpn-auth-ldap-2.0.4.log

This is more fallout to permit narrowing down failures:

=>> Building security/openvpn-auth-ldap
build started at Sun Jul 26 01:01:36 UTC 2020
port directory: /usr/ports/security/openvpn-auth-ldap
package name: openvpn-auth-ldap-2.0.4
building for: FreeBSD head-i386-default-job-12 13.0-CURRENT FreeBSD 13.0-CURRENT 1300101 i386
maintained by: mandree@FreeBSD.org
Makefile ident:      $FreeBSD: head/security/openvpn-auth-ldap/Makefile 527679 2020-03-03 15:11:46Z mat $
Poudriere version: 3.2.8-5-gc81843e5
Host OSVERSION: 1300100
Jail OSVERSION: 1300101
Job Id: 12

!!! Jail is newer than host. (Jail: 1300101, Host: 1300100) !!!
!!! This is not supported. !!!
!!! Host kernel must be same or newer than jail. !!!
!!! Expect build failures. !!!

---Begin Environment---
SHELL=/bin/csh
UNAME_p=i386
UNAME_m=i386
OSVERSION=1300101
UNAME_v=FreeBSD 13.0-CURRENT 1300101
UNAME_r=13.0-CURRENT
BLOCKSIZE=K
MAIL=/var/mail/root
STATUS=1
HOME=/root
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
LOCALBASE=/usr/local
USER=root
LIBEXECPREFIX=/usr/local/libexec/poudriere
POUDRIERE_VERSION=3.2.8-5-gc81843e5
MASTERMNT=/usr/local/poudriere/data/.m/head-i386-default/ref
POUDRIERE_BUILD_TYPE=bulk
PACKAGE_BUILDING=yes
SAVED_TERM=
PWD=/usr/local/poudriere/data/.m/head-i386-default/ref/.p/pool
P_PORTS_FEATURES=FLAVORS SELECTED_OPTIONS
MASTERNAME=head-i386-default
SCRIPTPREFIX=/usr/local/share/poudriere
OLDPWD=/usr/local/poudriere/data/.m/head-i386-default/ref/.p
SCRIPTPATH=/usr/local/share/poudriere/bulk.sh
POUDRIEREPATH=/usr/local/bin/poudriere
---End Environment---


git-svn-id: svn+ssh://svn.freebsd.org/ports/head@543455 35697150-7ecd-e111-bb59-0022644237b5
uqs pushed a commit to freebsd/freebsd-ports that referenced this issue Jul 26, 2020
The option is a linker option but is passed to cc verbatim, and this
causes fallout complaints on head i386 (13):

--- lemon ---
cc  -o lemon lemon.o  -export-dynamic
ld: warning: cannot find entry symbol xport-dynamic; defaulting to 0x4049B0
===> making all in src
--- all ---
--- auth-ldap.o ---
cc -fPIC  -O2 -pipe  -fPIC -fstack-protector-strong -DLDAP_DEPRECATED -fno-strict-aliasing  -Wno-import -L/usr/local/lib -I/usr/local/include -fPIC -I/usr/local/include  -D_THREAD_SAFE  -fobjc-exceptions -fno-strict-aliasing -O2 -pipe  -fPIC -fstack-protector-strong -DLDAP_DEPRECATED -fno-strict-aliasing  -DHAVE_CONFIG_H -Wall -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -c auth-ldap.m -o auth-ldap.o -I. -I../src -I.. -I../src -I. -I../tests -I../tests
--- TRConfigParser.m ---
./tools/lemon -T../tools/lempar.c -m -q TRConfigParser.lemon -OTRConfigParser.m
Segmentation fault (core dumped)
*** [TRConfigParser.m] Error code 139

NOTE! With devel/check exactly at 0.15.1, this fails to build due to a regression
in check 0.15.1. 0.15.0 is fine, and the bug is reported here:

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=248274 (FreeBSD)
libcheck/check#293 (upstream)

http://beefy17.nyi.freebsd.org/data/head-i386-default/p543393_s363499/logs/openvpn-auth-ldap-2.0.4.log

This is more fallout to permit narrowing down failures:

=>> Building security/openvpn-auth-ldap
build started at Sun Jul 26 01:01:36 UTC 2020
port directory: /usr/ports/security/openvpn-auth-ldap
package name: openvpn-auth-ldap-2.0.4
building for: FreeBSD head-i386-default-job-12 13.0-CURRENT FreeBSD 13.0-CURRENT 1300101 i386
maintained by: mandree@FreeBSD.org
Makefile ident:      $FreeBSD: head/security/openvpn-auth-ldap/Makefile 527679 2020-03-03 15:11:46Z mat $
Poudriere version: 3.2.8-5-gc81843e5
Host OSVERSION: 1300100
Jail OSVERSION: 1300101
Job Id: 12

!!! Jail is newer than host. (Jail: 1300101, Host: 1300100) !!!
!!! This is not supported. !!!
!!! Host kernel must be same or newer than jail. !!!
!!! Expect build failures. !!!

---Begin Environment---
SHELL=/bin/csh
UNAME_p=i386
UNAME_m=i386
OSVERSION=1300101
UNAME_v=FreeBSD 13.0-CURRENT 1300101
UNAME_r=13.0-CURRENT
BLOCKSIZE=K
MAIL=/var/mail/root
STATUS=1
HOME=/root
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
LOCALBASE=/usr/local
USER=root
LIBEXECPREFIX=/usr/local/libexec/poudriere
POUDRIERE_VERSION=3.2.8-5-gc81843e5
MASTERMNT=/usr/local/poudriere/data/.m/head-i386-default/ref
POUDRIERE_BUILD_TYPE=bulk
PACKAGE_BUILDING=yes
SAVED_TERM=
PWD=/usr/local/poudriere/data/.m/head-i386-default/ref/.p/pool
P_PORTS_FEATURES=FLAVORS SELECTED_OPTIONS
MASTERNAME=head-i386-default
SCRIPTPREFIX=/usr/local/share/poudriere
OLDPWD=/usr/local/poudriere/data/.m/head-i386-default/ref/.p
SCRIPTPATH=/usr/local/share/poudriere/bulk.sh
POUDRIEREPATH=/usr/local/bin/poudriere
---End Environment---
@brarcher
Copy link
Contributor

One other option that occurred to me is to have fail_if bypass the printf validation check, whereas the other assert macros continue to do so. Maybe something like this:

1da77e4

That definitely is a hack, but it should keep fail_if without arguments working. It does cause a new build warning on Clang, as the version of ck_assert_failed which does not validate its arguments is passing a non string literal to vsnprintf:

check.c:413:4: warning: format string is not a string literal [-Wformat-nonliteral]
   _ck_assert_failed_inner();
   ^~~~~~~~~~~~~~~~~~~~~~~~~
check.c:386:32: note: expanded from macro '_ck_assert_failed_inner'
        vsnprintf(buf, BUFSIZ, msg, ap);\
                               ^~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/secure/_stdio.h:75:63: note: 
      expanded from macro 'vsnprintf'
  __builtin___vsnprintf_chk (str, len, 0, __darwin_obsz(str), format, ap)
                                                              ^~~~~~

Does 1da77e4 look like it might work? Also, as a part of that change a new test will need to be added to check that confirms fail_if with no arguments continue to work.

Jehops pushed a commit to Jehops/freebsd-ports-legacy that referenced this issue Jul 26, 2020
The option is a linker option but is passed to cc verbatim, and this
causes fallout complaints on head i386 (13):

--- lemon ---
cc  -o lemon lemon.o  -export-dynamic
ld: warning: cannot find entry symbol xport-dynamic; defaulting to 0x4049B0
===> making all in src
--- all ---
--- auth-ldap.o ---
cc -fPIC  -O2 -pipe  -fPIC -fstack-protector-strong -DLDAP_DEPRECATED -fno-strict-aliasing  -Wno-import -L/usr/local/lib -I/usr/local/include -fPIC -I/usr/local/include  -D_THREAD_SAFE  -fobjc-exceptions -fno-strict-aliasing -O2 -pipe  -fPIC -fstack-protector-strong -DLDAP_DEPRECATED -fno-strict-aliasing  -DHAVE_CONFIG_H -Wall -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/usr/local/include -c auth-ldap.m -o auth-ldap.o -I. -I../src -I.. -I../src -I. -I../tests -I../tests
--- TRConfigParser.m ---
./tools/lemon -T../tools/lempar.c -m -q TRConfigParser.lemon -OTRConfigParser.m
Segmentation fault (core dumped)
*** [TRConfigParser.m] Error code 139

NOTE! With devel/check exactly at 0.15.1, this fails to build due to a regression
in check 0.15.1. 0.15.0 is fine, and the bug is reported here:

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=248274 (FreeBSD)
libcheck/check#293 (upstream)

http://beefy17.nyi.freebsd.org/data/head-i386-default/p543393_s363499/logs/openvpn-auth-ldap-2.0.4.log

This is more fallout to permit narrowing down failures:

=>> Building security/openvpn-auth-ldap
build started at Sun Jul 26 01:01:36 UTC 2020
port directory: /usr/ports/security/openvpn-auth-ldap
package name: openvpn-auth-ldap-2.0.4
building for: FreeBSD head-i386-default-job-12 13.0-CURRENT FreeBSD 13.0-CURRENT 1300101 i386
maintained by: mandree@FreeBSD.org
Makefile ident:      $FreeBSD: head/security/openvpn-auth-ldap/Makefile 527679 2020-03-03 15:11:46Z mat $
Poudriere version: 3.2.8-5-gc81843e5
Host OSVERSION: 1300100
Jail OSVERSION: 1300101
Job Id: 12

!!! Jail is newer than host. (Jail: 1300101, Host: 1300100) !!!
!!! This is not supported. !!!
!!! Host kernel must be same or newer than jail. !!!
!!! Expect build failures. !!!

---Begin Environment---
SHELL=/bin/csh
UNAME_p=i386
UNAME_m=i386
OSVERSION=1300101
UNAME_v=FreeBSD 13.0-CURRENT 1300101
UNAME_r=13.0-CURRENT
BLOCKSIZE=K
MAIL=/var/mail/root
STATUS=1
HOME=/root
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
LOCALBASE=/usr/local
USER=root
LIBEXECPREFIX=/usr/local/libexec/poudriere
POUDRIERE_VERSION=3.2.8-5-gc81843e5
MASTERMNT=/usr/local/poudriere/data/.m/head-i386-default/ref
POUDRIERE_BUILD_TYPE=bulk
PACKAGE_BUILDING=yes
SAVED_TERM=
PWD=/usr/local/poudriere/data/.m/head-i386-default/ref/.p/pool
P_PORTS_FEATURES=FLAVORS SELECTED_OPTIONS
MASTERNAME=head-i386-default
SCRIPTPREFIX=/usr/local/share/poudriere
OLDPWD=/usr/local/poudriere/data/.m/head-i386-default/ref/.p
SCRIPTPATH=/usr/local/share/poudriere/bulk.sh
POUDRIEREPATH=/usr/local/bin/poudriere
---End Environment---


git-svn-id: svn+ssh://svn.freebsd.org/ports/head@543455 35697150-7ecd-e111-bb59-0022644237b5
heftig referenced this issue Jul 27, 2020
There are some uses of fail_if in libcheck users which do not
supply an argument. fail_if() expects an argument, though when
none is provided it is ignored.

Check 0.15.0 (and a fix in 0.15.1) added printf argument validation
to the assert macros. As a result, instances of fail_if with
no arguments are now being flagged.

To support fail_if() without arguments, a new _ck_assert_failed*
method is being added whose purpose is to act just like
_ck_assert_failure but no printf validation is done on its
arguments by the compiler.
@heftig
Copy link

heftig commented Jul 27, 2020

I think the lazy fix for this would be adding back the extra NULL argument to the deprecated fail* macros.

You would have to tell projects which continue using the deprecated macros to either ignore the -Wformat-extra-args warning this causes (if they try to pass a message) or to port their tests to the non-deprecated macros.

@heftig
Copy link

heftig commented Jul 27, 2020

Something like this, I think:

diff --git c/src/check.h.in i/src/check.h.in
index 56187fb..c6d4eb3 100644
--- c/src/check.h.in
+++ i/src/check.h.in
@@ -466,29 +466,32 @@ static void __testname ## _fn (int _i CK_ATTRIBUTE_UNUSED)
  *
  * This call is deprecated.
  */
-#define fail_unless ck_assert_msg
+#define fail_unless(expr, ...) \
+  (expr) ? \
+     _mark_point(__FILE__, __LINE__) : \
+     _ck_assert_failed(__FILE__, __LINE__, "Assertion '"#expr"' failed" , ## __VA_ARGS__, NULL)
 
 /*
  * Fail the test case if expr is false
  *
  * This call is deprecated.
  *
  * NOTE: The space before the comma sign before ## is essential to be compatible
  * with gcc 2.95.3 and earlier.
  * FIXME: these macros may conflict with C89 if expr is
  * FIXME:   strcmp (str1, str2) due to excessive string length.
  */
 #define fail_if(expr, ...)\
   (expr) ? \
-     _ck_assert_failed(__FILE__, __LINE__, "Failure '"#expr"' occurred" , ## __VA_ARGS__) \
+     _ck_assert_failed(__FILE__, __LINE__, "Failure '"#expr"' occurred" , ## __VA_ARGS__, NULL) \
      : _mark_point(__FILE__, __LINE__)
 
 /*
  * Fail the test
  *
  * This call is deprecated.
  */
-#define fail ck_abort_msg
+#define fail(...) _ck_assert_failed(__FILE__, __LINE__, "Failed" , ## __VA_ARGS__, NULL)
 
 /*
  * This is called whenever an assertion fails.

brarcher added a commit that referenced this issue Aug 2, 2020
The fail, fail_unless, and fail_if APIS were expected to contain
a message explaining the failure. This was never enforced, and
it was possible to write unit tests without providing messages.

In github.com//pull/249 a change was
introduced to add printf argument checking to the Check assert
APIS, including the fail APIs. There were a few fixes for this
in github.com/libcheck/check/releases/tag/0.15.1. Those changes
proved problematic for the uses of the fail* APIs without arguments,
as those uses were now flagged as missing the necessary arguments.

A fix proposed by heftig in github.com//issues/293
is to add a new NULL to the end of every fail* call in the macro
itself. For users of these APIs who do pass a message there will
be a new warning about too many arguments. As the fail APIs are
deprecated, this new warning is a reasonable trade-off, and can
be avoided by switching fail* calls to ck_assert* calls.
@brarcher
Copy link
Contributor

brarcher commented Aug 2, 2020

@heftig, that is a pretty straight-forward idea, thanks for it. That should work. I'll pull that change in.

@brarcher
Copy link
Contributor

brarcher commented Aug 3, 2020

This should now be resolved by #298

@brarcher brarcher closed this as completed Aug 3, 2020
@buscher
Copy link
Author

buscher commented Aug 3, 2020

Thanks for the fix! :)

Will there be a 0.15.2 release for this?
And are there some (more or less) concrete plans to remove the deprecated fail_* ? For example for 0.16? 0.20? Expected date?

@brarcher
Copy link
Contributor

brarcher commented Aug 4, 2020

I'll be cutting a release with just the fix in a few days. That will be 0.15.2.

I do not currently have a plan for removing the deprecate APIs. With #298 there now may be a warning when using the fail* APIs. Otherwise, the APIs continue to work. If the fail* APIs are to be removed, I'll research what a good plan for doing so looks like, communicate it, and give lots of warning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants