Giter Club home page Giter Club logo

Comments (11)

brarcher avatar brarcher commented on July 21, 2024

@9fcc:
While attempting to get unit tests running on AppVeyor (see #99) I hit this issue. I can help debug the issue further, if it is helpful. Additionally, AppVeyor allows one to RDP into a running VM and poke around, which is how I figured out what I did:

https://www.appveyor.com/docs/how-to/rdp-to-build-worker/

from check.

9fcc avatar 9fcc commented on July 21, 2024

Once I had the same issue on Linux. What optimization level was used while compiling? It must be 0 to determine the real issue. Compiler can optimize strlen passed directly to the function in such a way that in would be a crash. But if temporary variable is used than optimization goes ok.
But in this case standard function used it internally, all arguments passed to the function are macro constants. So strlen just could not get segfault by itself.

ap argument need to be checked too. Right now I haven't much time.

Moreover Check has a lot of erroneous code by itself, it could be the issue to. It violates on of the CERT rules ('\0' must be added to a buffer after snprintf call). It can cause segmentation faults too.

from check.

brarcher avatar brarcher commented on July 21, 2024

I've tried to simplify this case to determine the minimum which will cause the failure. Running a simple program using the following did cause the problem:

 void do_the_print(const char *expr, ...)
 {
     const char *msg;
     va_list ap;
     char buf[BUFSIZ];
     printf("BUFSIZ: %d\n", BUFSIZ);
 
     va_start(ap, expr);
 
     vsnprintf(buf, BUFSIZ, expr, ap);
     printf("%s\n", buf);
 
     va_end(ap);
 }
  
  #define MY_FLOATING_DIG 6
  
 #define example_macro(X, OP, Y, TP, TM) do { \
    TP _ck_x = (X); \
    TP _ck_y = (Y); \
    do_the_print("Assertion '%s' failed: %s == %.*"TM"g, %s == %.*"TM"g", \
   #X" "#OP" "#Y, \
   #X, (int)MY_FLOATING_DIG, _ck_x, \
   #Y, (int)MY_FLOATING_DIG, _ck_y); \
 } while (0)
          
int main()
{
   example_macro((double)1/(double)3, ==, 1.5, double, "l");
   return 0;
}

That results in the SIGSEGV on Windows 2012. However, on OSX the following is printed:

BUFSIZ: 1024
Assertion '(double)1/(double)3 == 1.5' failed: (double)1/(double)3 == 0.333333, 1.5 == 1.5

from check.

brarcher avatar brarcher commented on July 21, 2024

I'll look into optimization levels and the other points that you mentioned.

from check.

9fcc avatar 9fcc commented on July 21, 2024

I did not check if %.* format is in POSIX or C99 standard. So can you replace it by %g for the test? And remove (int)MY_FLOATING_DIG,.

from check.

brarcher avatar brarcher commented on July 21, 2024

Removing the * and specifying the precision inline (%.6lg) does prevent the SIGSEGV, however the printout is not as expected.

OSX:

Assertion '(double)1/(double)3 == 1.5' failed: (double)1/(double)3 == 0.333333, 1.5 == 1.5

MinGW:

Assertion '(double)1/(double)3 == 1.5' failed: (double)1/(double)3 == -0, (null) == 0

Removing the precision specifier altogether and only using %lg printed the same on MinGW.

According to the printf man page on OSX from BSD, the 'l' specifier is unnecessary for double:

         Modifier    a, A, e, E, f, F, g, G
         l (ell)     double (ignored, same behavior as without it)
         L           long double

Attempting to remove that and use %.6g I get the following:

OSX:

Assertion '(double)1/(double)3 == 1.5' failed: (double)1/(double)3 == 0.333333, 1.5 == 1.5

MinGW:

Assertion '(double)1/(double)3 == 1.5' failed: (double)1/(double)3 == 0.333333, 1.5 == 1.5

So, it would seem that there are two things that need to be updated in the floating macros to get broader support:

  1. Remove the .* from the printf specifier and hardcode the percision inline.
  2. Remove the "l" specifier for double, as it is ignored on some platforms and causes problems on others.

from check.

9fcc avatar 9fcc commented on July 21, 2024

I still want to check something for understanding. It's a very strange segfault. Can you replace (int)MY_FLOATING_DIG with a temporary variable in the minimal test?

from check.

9fcc avatar 9fcc commented on July 21, 2024

And I did not found the C standard used to compile Check with configure.ac nor with CMakeLists.txt. How is it determined? "lf" modifier is allowed by C99 standard and it is the same as "f". As this table shows printf realization goes to libc:
https://gcc.gnu.org/c99status.html
I wander what library is user with MinGW because it just does not support C99 or has a bug. Or C89 standard was enabled by default. And using C89 for me is ridiculous.

from check.

brarcher avatar brarcher commented on July 21, 2024

Can you replace (int)MY_FLOATING_DIG with a temporary variable in the minimal test?

I attempted this, so the macro became:

#define example_macro(X, OP, Y, TP, TM) do { \
  TP _ck_x = (X); \
  TP _ck_y = (Y); \
  int MY_FLOATING_DIG = 6; \
  do_the_print("Assertion '%s' failed: %s == %.*"TM"g, %s == %.*"TM"g", \
  #X" "#OP" "#Y, \
  #X, (int)MY_FLOATING_DIG, _ck_x, \
  #Y, (int)MY_FLOATING_DIG, _ck_y); \
} while (0)

example_macro((double)1/(double)3, ==, 1.5, double, "");

This was successful, printing the following in MinGW:

Assertion '(double)1/(double)3 == 1.5' failed: (double)1/(double)3 == 0.333333, 1.5 == 1.5

However, adding back the "l" for the modifier, specially:

example_macro((double)1/(double)3, ==, 1.5, double, "l");

still caused a SIGSEGV on MinGW.

from check.

brarcher avatar brarcher commented on July 21, 2024

And I did not found the C standard used to compile Check with configure.ac nor with CMakeLists.txt. How is it determined?

I do not think that Check explicitly compiles with any particular C standard specified, but instead the features in Check try to stay in C99.

"lf" modifier is allowed by C99 standard and it is the same as "f".
I wander what library is user with MinGW because it just does not support C99 or has a bug.

I agree, according to the following from that link:

%lf conversion specifier allowed in printf	Library feature, no compiler support required (format checking support present).

According to the following link, the issue arises between mixing gcc and the MSVC runtime, which is what MinGW does:

http://stackoverflow.com/questions/7134547/gcc-printf-and-long-double-leads-to-wrong-output-c-type-conversion-messes-u

Specifically, the following describes what is doing on between double and long double:

The other part of this problem you're running into is that long double in GCC is a 
different type  than long double in MSVC. GCC uses a 96-bit or 128-bit type for 
long double on x86 or x64 targets 
(see http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html). 
However, MSVC uses a 64-bit type - basically long double is exactly the same 
as double for msvcrt.dll 
(http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx)

Would have never guess that.

from check.

brarcher avatar brarcher commented on July 21, 2024

This issue was resolved in #102.

from check.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.