Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
giogadi
Oct 27, 2009

Volte posted:

Unsigned int should usually mean "raw bit pattern" not "integer value that logically can't be negative". Sometimes even values that can't be negative can be subtracted from and you end up with really stupid bugs when the difference would be negative. Subtracting two vector sizes to get the difference between them? Better make drat sure to check which one's bigger first.

Absolutely correct. Better than I could phrase it

Adbot
ADBOT LOVES YOU

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
There was a big push to do a "stl2" alongside ranges which would fix a lot of the incidental minor problems, and switching to using signed sizes and reserving unsigned for things you don't do math on was part of that. That project didn't get committee buy-in, though.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Plorkyeran posted:

There was a big push to do a "stl2" alongside ranges which would fix a lot of the incidental minor problems, and switching to using signed sizes and reserving unsigned for things you don't do math on was part of that. That project didn't get committee buy-in, though.
Non-serious counterpoint to signed sizes are good - Microsoft loving things up by using 32-bit size_t for posix file operations unless you go out of your way to #define some poo poo would be *even worse* if the accidental maximum size was ~2GB instead of ~4GB.

(Though yuck, ssize_t and size_t, instead of size_t and usize_t)

giogadi
Oct 27, 2009

roomforthetuna posted:

Non-serious counterpoint to signed sizes are good - Microsoft loving things up by using 32-bit size_t for posix file operations unless you go out of your way to #define some poo poo would be *even worse* if the accidental maximum size was ~2GB instead of ~4GB.

(Though yuck, ssize_t and size_t, instead of size_t and usize_t)

Hahaha what the gently caress

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

giogadi posted:

Hahaha what the gently caress
To be fair it might not be Microsoft being weird, it might be the defaults of some other environment being weird - I do some work on an open-source thing that uses bazel and tries to be cross-platform compatible, and Microsoft's / Windows's size_t are definitely a gently caress in that particular context.

His Divine Shadow
Aug 7, 2000

I'm not a fascist. I'm a priest. Fascists dress up in black and tell people what to do.
Is it bad form in c to write one over the other. From what I understand they should be equivalent since an array in c is just a pointer in disguise.

code:
int function(char var[]) {}

//instead of

int function(char var*) {}
Someone commented somewhere the 2nd was preferrable but I dunno why.

Xarn
Jun 26, 2015
I prefer the second because it isn't lying.

Beef
Jul 26, 2004
Except when it's actually an array as in "int arr[3]".

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum

Beef posted:

Except when it's actually an array as in "int arr[3]".

This doesn’t work well in my experience, can’t remember why though

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.
Just here to echo that the landmines around ever subtracting from a size_t are real and one of the handful of moments that actually made me swear out loud during my return to C++ over the last few months.

It should have been signed. I guess that we're still living with the decisions made when pointers were much smaller, and will be forever.

Xarn
Jun 26, 2015

Beef posted:

Except when it's actually an array as in "int arr[3]".

nope, that's not a thing

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

edit: I may have misunderstood beef's point; deleting

Dijkstracula fucked around with this message at 16:14 on Jan 9, 2023

Xarn
Jun 26, 2015
There is actually a way to declare function argument that takes an array of **at least** n arguments, but the enforcement is that it is UB to not do that and maybe your static analysis tool will warn if you didn't pass in the right array.

Beef
Jul 26, 2004

Xarn posted:

nope, that's not a thing

Ah crap, you're right. Better post caffeinated.

quote:

any parameter of array type is adjusted to the corresponding pointer type, which may be qualified if there are qualifiers between the square brackets of the array declarator (since C99)
code:
int f(int[]); // declares int f(int*)
int g(const int[10]); // declares int g(const int*)
int h(int[const volatile]); // declares int h(int * const volatile)
int x(int[*]); // declares int x(int*)

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
Note that while int* and int[] are identical in argument lists, and a type like int[5] is silently ignored / transformed into int*,
you can have a variable of type "pointer to an array of length N"

code:
// x must be a pointer to an array of exactly length 3
void foo(int (*x)[3]) {
  printf ("%d %d %d", (*x)[0],(*x)[1], (*x)[2]);
  
  // or equivalently:
  int* arr = *x;
  printf ("%d %d %d", arr[0], arr[1], arr[2]);
}

int main(void) {
  // compiles:
  int bar[3] = {3, 5, 7};
  foo(&bar);

  //does not compile:
  int baz[4] = {3, 9, 29, 81};
  foo(&baz);
 
  //doesn't work with a malloc'd array either, since the type is int**
  int qux = malloc(3 * sizeof(int));
  foo(&qux);
}
This is really not that useful though, you should just define a struct if you need to pass a bundle of exactly three variables.

RPATDO_LAMD fucked around with this message at 21:37 on Jan 9, 2023

StumblyWumbly
Sep 12, 2007

Batmanticore!
There are situations where it's a nice note for how many bytes an output parameter will return, like

code posted:

bool read_2_bytes(uint8_t bytes[2]);
But there's no enforcement on it and it kinda looks like you don't know what you're doing.

Ihmemies
Oct 6, 2012

Does anyone use Qt creator? I want to limit the clang to specific C standard: https://clang.llvm.org/c_status.html

It says I can use something like -std=c90

Qt says it's an invalid option and discards it if I try to use it:



Any pro tips? Do I need to put it somewhere else?

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.

Ihmemies posted:

Does anyone use Qt creator? I want to limit the clang to specific C standard: https://clang.llvm.org/c_status.html

It says I can use something like -std=c90

Qt says it's an invalid option and discards it if I try to use it:



Any pro tips? Do I need to put it somewhere else?

What C standard are you wanting to use? C90 is not a standard, as the clang docs you linked mention you probably want c89 if you're trying to intentionally write c that builds with ancient or tiny compilers, but I'm curious what those are? C11 is really widely supported at this point.

OddObserver
Apr 3, 2009
Maybe because -std is not a warning option?

Ihmemies
Oct 6, 2012

Twerk from Home posted:

What C standard are you wanting to use? C90 is not a standard, as the clang docs you linked mention you probably want c89 if you're trying to intentionally write c that builds with ancient or tiny compilers, but I'm curious what those are? C11 is really widely supported at this point.

I am doing a C course, which has automated checks for exercises. It gives prompts like:

code:
/tmp/weto/kertotaulu.c:18:5: error: C++ style comments are not allowed in ISO C90
     // first row

/tmp/weto/kertotaulu.c:19:5: error: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
     int num = 1;
If I try to do something nasty. Ad infinitum. I can't remember all the limitations so it would helpful if the program reminded me about "No sir you couldn't do that 33 years ago!" :v:

OddObserver posted:

Maybe because -std is not a warning option?

Maybe. I don't really understand this. So it's not possible to get warnings about something like for(int i = 0; i < 7; i++) { ... ?

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.
I'm dumb, ANSI C is apparently also called c90 as well as c89, my bad.

Yes, you want your compiler in that mode, and then just turn up the warnings.

Xarn
Jun 26, 2015

StumblyWumbly posted:

There are situations where it's a nice note for how many bytes an output parameter will return, like
C code:
bool read_2_bytes(uint8_t bytes[2]);
But there's no enforcement on it and it kinda looks like you don't know what you're doing.

C code:
bool read_2_bytes(uint8_t bytes[static 2]);
not to be confused with

C code:
bool read_2_bytes(uint8_t bytes[restrict 2]);
:eng101:

OddObserver
Apr 3, 2009

Ihmemies posted:


Maybe. I don't really understand this. So it's not possible to get warnings about something like for(int i = 0; i < 7; i++) { ... ?

Edit: -Wc99-extensions may be what you were trying for, but you probably do want the -std for compilation as well.
(See https://clang.llvm.org/docs/DiagnosticsReference.html#id145)

So I don't know what Qt Creator is thinking, but the option stuck out since it doesn't enable a warning for those things, it makes them an error, so I was guessing Qt creator may expect you to put into some other bunch of settings (e.g. language settings for compilation?)

OddObserver fucked around with this message at 19:30 on Jan 10, 2023

Ihmemies
Oct 6, 2012

I had to add Kits > Compilers > a manual compiler with flag like -ansi or -std=c90. Then use that Kit in the Qt project.

I'm supposed to print a list of repeating numbers from an array, which gets its values as cmd parameter like 0.2 -9.9 4.32 0.2 -9.9 1.23 15 0.2 -9.9...

I'm not supposed to create my own arrays, instead I must iterate over that argv array repeatedly.

code:
Most often (3 times): 0.200000 -9.900000 0.200000 -9.900000 0.200000 -9.900000
I've been at this for a couple of days, and I can't figure out how to print the numbers only once. How can I know if I have printed a number already or not, hnghhhh

If I just could make an array which tracks if a number from given index is printed or not... or something something

Ihmemies fucked around with this message at 16:59 on Jan 15, 2023

Computer viking
May 30, 2011
Now with less breakage.

Ihmemies posted:

I had to add Kits > Compilers > a manual compiler with flag like -ansi or -std=c90. Then use that Kit in the Qt project.

I'm supposed to print a list of repeating numbers from an array, which gets its values as cmd parameter like 0.2 -9.9 4.32 0.2 -9.9 1.23 15 0.2 -9.9...

I'm not supposed to create my own arrays, instead I must iterate over that argv array repeatedly.

code:
Most often (3 times): 0.200000 -9.900000 0.200000 -9.900000 0.200000 -9.900000
I've been at this for a couple of days, and I can't figure out how to print the numbers only once. How can I know if I have printed a number already or not, hnghhhh

If I just could make an array which tracks if a number from given index is printed or not... or something something

Are you allowed to rearrange it?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Loops aren’t required to cover the entire array. Think about how you’d write a loop that just walks the start of the array, or the end of it, or visits every other element. Then think about how you might use those things here.

Ihmemies
Oct 6, 2012

I ended up traversing the list yet again. If the same number was in the list before the current position, there was no need to print it again.

Anyways, I made this truly awful solution to print correct amount of separators ',' between the words. Is there.. some better way to do this... this is horrible... The program tells to what limits the given number fits. Printout is something like this:

code:
-293: short int, int
7608: short int, unsigned short int, int
-127: signed char, short int, int
1234567: int
0: signed char, unsigned char, short int, unsigned short int, int
C code:
int main(int argc, char *argv[])
{
    int value;
    int i = 1;
    int sep = -1;

    for (; i < argc; i++) {
        value = atoi(argv[i]);
        sep = -1;

        printf("%d:", value);

        /* research the amount of separators needed */
        if (value >= -128 && value <= 127) {
            sep++;
        }
        if (value >= 0 && value <= 255) {
            sep++;
        }
        if (value >= -32768 && value <= 32767) {
            sep++;
        }
        if (value >= 0 && value <= 65535) {
            sep++;
        }
        if (value >= -2147483647 && value <= 2147483647) {
            sep++;
        }

        if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
            printf(" signed char");
            if (sep > 0) {
                putchar(',');
                sep--;
            }
        }
        if (value >= 0 && value <= UCHAR_MAX) {
            printf(" unsigned char");
            if (sep > 0) {
                putchar(',');
                sep--;
            }
        }
        if (value >= SHRT_MIN && value <= SHRT_MAX) {
            printf(" short int");
            if (sep > 0) {
                putchar(',');
                sep--;
            }
        }
        if (value >= 0 && value <= USHRT_MAX) {
            printf(" unsigned short int");
            if (sep > 0) {
                putchar(',');
                sep--;
            }
        }
        if (value >= INT_MIN && value <= INT_MAX) {
            printf(" int");
            if (sep > 0) {
                putchar(',');
                sep--;
            }
        }

        putchar('\n');

    }

    return 0;
}

Ihmemies fucked around with this message at 17:35 on Jan 17, 2023

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Try printing separators before items.

Ihmemies
Oct 6, 2012

rjmccall posted:

Try printing separators before items.

:captainpop:

At this rate I never will be a good enough at coding.

Computer viking
May 30, 2011
Now with less breakage.

Ihmemies posted:

:captainpop:

At this rate I never will be a good enough at coding.

It's a long journey of banging your head on practical things like that and then eventually gluing all those little tricks you've learned into functional-enough code in whatever language you happen to be using at the time.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
You can also avoid having to copy-paste that code for every separate type by separating it out into a function or a loop body. In the case of a loop you'd need to put all your min/max bounds and strings-to-print into a hard-coded array of some kind.
Not a huge deal with only 5 options but if you are gonna modify that code later to add the rest of the C integer types it would be a lot easier without the code duplication

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


Ihmemies posted:

:captainpop:

At this rate I never will be a good enough at coding.

Just try not to make the same mistake twice and you'll be a pro in no time.

Ihmemies
Oct 6, 2012

I made a struct for storing one entry, and added the structs to a struct array... never used these before I think, but at least it works!

C code:

/* intro struct for limit data*/
struct limit {
    char str[20];
    int min;
    int max;
};

/* create array with limits */
struct limit limits[5] = {
    {"signed char", SCHAR_MIN, SCHAR_MAX },
    {"unsigned char", 0, UCHAR_MAX },
    {"short int", SHRT_MIN, SHRT_MAX },
    {"unsigned short int", 0, USHRT_MAX},
    {"int", INT_MIN, INT_MAX}
};

static const int MAX_LIMITS = 5;

int main(int argc, char *argv[])
{
    int value;
    int i = 1; 
    int j = 0;
    bool first = true;

    /* loop through the cmdline params */
    for (; i < argc; i++) {
        value = atoi(argv[i]);
        first = true;

        printf("%d:", value);

        /* loop through the defined limits */
        for (j = 0; j < MAX_LIMITS; j++) {
            if (value >= limits[j].min && value <= limits[j].max) {
                if (!first) putchar(',');
                else first = false;
                printf(" %s", limits[j].str);

            }
        }
        /* new line for new number */
        putchar('\n');
    }

    return 0;
}
Thanks for the idea.

mmkay
Oct 21, 2010

A small nitpick/hint, but you can automatically calculate the MAX_LIMITS based on the sizeof of the limits array (since it's statically allocated). That way it's more tightly coupled with it, which is what you want (you won't have to remember to change two places at once).

Ihmemies
Oct 6, 2012

Thanks, I will do that too. It is a school exercise but I guess I can make it suck less, just to learn more. Only a machine will look at the code.

Volguus
Mar 3, 2009
Are there some resources somewhere on how could one use Boost ASIO ssl::stream with TLS-PSK? There was a patch submitted to Boost about 10 years ago, which was not accepted since it had a number of issues, but otherwise google is quite helpless in this regard. Thank you.

ullerrm
Dec 31, 2012

Oh, the network slogan is true -- "watch FOX and be damned for all eternity!"

Volguus posted:

Are there some resources somewhere on how could one use Boost ASIO ssl::stream with TLS-PSK? There was a patch submitted to Boost about 10 years ago, which was not accepted since it had a number of issues, but otherwise google is quite helpless in this regard. Thank you.

Calling native_handle() on your ssl::context will let you get to the underlying SSL_CTX from OpenSSL. Then, you can use SSL_CTX_set_psk_client_callback() (or one of the new find-session variants) to register a callback for providing PSKs. When OpenSSL does its negotiations, it'll call your callback to find and provide a PSK.

The rejected patch is just making the old app-based version of that call and wrapping it in Boost idioms.

Volguus
Mar 3, 2009

ullerrm posted:

Calling native_handle() on your ssl::context will let you get to the underlying SSL_CTX from OpenSSL. Then, you can use SSL_CTX_set_psk_client_callback() (or one of the new find-session variants) to register a callback for providing PSKs. When OpenSSL does its negotiations, it'll call your callback to find and provide a PSK.

The rejected patch is just making the old app-based version of that call and wrapping it in Boost idioms.

That's what I'm trying ... yet, I'm missing something. Here's the simplest server:

C++ code:
static unsigned int sslpsk_psk_server_callback(SSL *ssl,
                                               const char *identity,
                                               unsigned char *psk,
                                               unsigned int max_psk_lens)
{
    std::cout << "identity : " << identity<< std::endl;
    strncpy((char*)psk,"foo", 3);
    return 3;
}

int main()
{

    boost::asio::ssl::context ssl_context(boost::asio::ssl::context::tls_server);
//    ssl_context.set_options(boost::asio::ssl::context::default_workarounds
//                            | boost::asio::ssl::context::no_sslv2);
    ssl_context.set_verify_mode(boost::asio::ssl::verify_peer);
    SSL_CTX_set_cipher_list(ssl_context.native_handle(),"TLS_CHACHA20_POLY1305_SHA256");
    boost::asio::io_context ctx;
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(ctx, ssl_context);    
    SSL_set_psk_server_callback(socket.native_handle(), sslpsk_psk_server_callback);
    SSL_set_accept_state(socket.native_handle());

    boost::asio::ip::tcp::acceptor acceptor(socket.get_executor(),
                                            boost::asio::ip::tcp::endpoint(
                                                boost::asio::ip::make_address("127.0.0.1"),4567));
    acceptor.listen();
    for(;;)
    {
        boost::asio::ssl::stream<boost::asio::ip::tcp::socket> client(ctx,ssl_context);
        acceptor.accept(client.next_layer());       
        std::cout << "client connected"<<std::endl;
        client.handshake(boost::asio::ssl::stream_base::server);
        boost::asio::write(client, boost::asio::buffer("abc",3));
    }

    return 0;
}

and client:
C++ code:
unsigned int sslpsk_psk_client_callback(SSL* ssl,
                                               const char* hint,
                                               char* identity,
                                               unsigned int max_identity_len,
                                               unsigned char* psk,
                                               unsigned int max_psk_len)
{
    std::cout << "hint : " << hint<< std::endl;
    strncpy((char*)identity,"cli", 3);
    identity[3]=0;
    strncpy((char*)psk,"foo", 3);
    psk[3]=0;
    return 3;
}

int main()
{
    boost::asio::ssl::context ssl_context(boost::asio::ssl::context::tls_client);
//    ssl_context.set_options(boost::asio::ssl::context::default_workarounds
//                            | boost::asio::ssl::context::no_sslv2);
//    ssl_context.set_verify_mode(boost::asio::ssl::verify_peer);
    SSL_CTX_set_cipher_list(ssl_context.native_handle(),"TLS_CHACHA20_POLY1305_SHA256");
    boost::asio::io_context ctx;
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(ctx, ssl_context);
    SSL_set_psk_client_callback(socket.native_handle(), sslpsk_psk_client_callback);
    SSL_set_connect_state(socket.native_handle());
    boost::asio::ip::tcp::resolver resolver(ctx);
    boost::asio::connect(socket.next_layer(),resolver.resolve("127.0.0.1","4567"));
    socket.handshake(boost::asio::ssl::stream_base::client);
    std::cout << "connected\n";
    char data[3];
    boost::asio::read(socket,boost::asio::buffer(data,3));

    std::cout << data<< std::endl;

    return 0;
}
If I don't call handshake (should I?) then the client just fails to read anything, and the exception thrown on the server is write: uninitialized (SSL routines) [asio.ssl:167772436]. If I call handshake then both client and server fail to do the handshake with handshake: no shared cipher (SSL routines)

I tried ALL as ciphers list. Same thing. I obviously have no idea how to even approach this, what exactly am I missing here.
The callbacks are not called in either server or client, so I'm wondering if there's more setup that I need to do.

Volguus fucked around with this message at 07:51 on Jan 21, 2023

Volguus
Mar 3, 2009
Got it working, that is, the client and the server exchange data as expected. There are a number of lessons I've learned and still a few questions.

1. I do have to call handshake (duh)
2. On the server side, if I want to set the callback (SSL_set_psk_server_callback) on the socket and not on the context, I have to set it on the client's socket, the one that I receive after calling accept. Makes sense now. Or just set the callbacks on the context and not worry about it.
3. If I want to use the new API (set_psk_find_session_callback and set_psk_use_session_callback ) either on the context or on the socket I still have to use the old APIs. Without it, the handshake fails. I have no idea why. The old callbacks do not get called, however. From the documentation (and from your previous post) it seems that I could use either, the new would replace the old, but in practice it doesn't seem to be the case (or, again, I'm making some dumb mistake).

Getting inspiration from the official openssl application (server and client) it looks like they're getting the cipher to use in the new API via

C code:
const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
....
cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id);
Surely those constants must have some human readable #defines somewhere, but I didn't find them.
The callbacks for the new APIs seem a bit strange, not sure what's the advantage over the old ones, especially since it seems that I still have to define and set the old callbacks.

Adbot
ADBOT LOVES YOU

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm about to walk into a forest of rakes on the ground in some code using Boost asio. It has a bunch of leaks in it, which makes me think the implementation isn't cleanly shutting it down properly. Are there some directions or patterns on that in general? In the past without other coroutine engines, I've seen various goofy ways to do it like scheduling a termination coroutine as an example, so I don't think it's going to be trivial.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply