Skip to contentSkip to conversation

options.c: fix broken unary minus usage

PATCH Superseded Lev Stipakov 6 participants 16 messages Oct 8, 2018 – Oct 11, 2018

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 options.c: fix broken unary minus usage

From: Lev Stipakov <[email protected]...>

In Visual Studio when unary minus is applied to unsigned, result is still unsigned. This means that when we use result as function formal parameter, we pass incorrect value.

Fix by adding explicit cast to signed type.

Since GCC doesn't complain (and users too :), it probably casts to signed automatically.

---
 src/openvpn/options.c | 2 +-
 src/openvpn/ssl.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
src/openvpn/options.c +1 -1
index e42029c..1927a32 100644
@@ -3509,7 +3509,7 @@ calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
         struct key_type fake_kt;
         init_key_type(&fake_kt, o->ciphername, o->authname, o->keysize, true,
                       false);
-        frame_add_to_extra_frame(&fake_frame, -(crypto_max_overhead()));
+        frame_add_to_extra_frame(&fake_frame, -(int)(crypto_max_overhead()));
         crypto_adjust_frame_parameters(&fake_frame, &fake_kt, o->replay,
                                        cipher_kt_mode_ofb_cfb(fake_kt.cipher));
         frame_finalize(&fake_frame, o->ce.link_mtu_defined, o->ce.link_mtu,
src/openvpn/ssl.c +1 -1
index 315303b..18b1fbd 100644
@@ -1987,7 +1987,7 @@ tls_session_update_crypto_params(struct tls_session *session,
     }
 
     /* Update frame parameters: undo worst-case overhead, add actual overhead */
-    frame_add_to_extra_frame(frame, -(crypto_max_overhead()));
+    frame_add_to_extra_frame(frame, -(int)(crypto_max_overhead()));
     crypto_adjust_frame_parameters(frame, &session->opt->key_type,
                                    options->replay, packet_id_long_form);
     frame_finalize(frame, options->ce.link_mtu_defined, options->ce.link_mtu,
Signature · 1 line
2.7.4
#1 lore raw

Hi,

Quoted 36 lines · Lev Stipakov

From: Lev Stipakov <[email protected]...>

In Visual Studio when unary minus is applied to unsigned, result is still unsigned. This means that when we use result as function formal parameter, we pass incorrect value.

Fix by adding explicit cast to signed type.

Since GCC doesn't complain (and users too :), it probably casts to signed automatically.

---
 src/openvpn/options.c | 2 +-
 src/openvpn/ssl.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
src/openvpn/options.c +1 -1
index e42029c..1927a32 100644
@@ -3509,7 +3509,7 @@ calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
         struct key_type fake_kt;
         init_key_type(&fake_kt, o->ciphername, o->authname, o->keysize, true,
                       false);
-        frame_add_to_extra_frame(&fake_frame, -(crypto_max_overhead()));
+        frame_add_to_extra_frame(&fake_frame, -(int)(crypto_max_overhead()));
         crypto_adjust_frame_parameters(&fake_frame, &fake_kt, o->replay,
                                        cipher_kt_mode_ofb_cfb(fake_kt.cipher));
         frame_finalize(&fake_frame, o->ce.link_mtu_defined, o->ce.link_mtu,
src/openvpn/ssl.c +0 -0
index 315303b..18b1fbd 100644

src/openvpn/ssl.c tls_session_update_crypto_params(struct tls_session *session, · line 1993

Quoted 8 lines
src/openvpn/ssl.c +1 -1
@@ -1987,7 +1987,7 @@ tls_session_update_crypto_params(struct tls_session *session,
     }
 
     /* Update frame parameters: undo worst-case overhead, add actual overhead */
-    frame_add_to_extra_frame(frame, -(crypto_max_overhead()));
+    frame_add_to_extra_frame(frame, -(int)(crypto_max_overhead()));
     crypto_adjust_frame_parameters(frame, &session->opt->key_type,
                                    options->replay, packet_id_long_form);
     frame_finalize(frame, options->ce.link_mtu_defined, options->ce.link_mtu,

Good catch. I had to look it up, but I think this is actually undefined behaviour. 6.5 point 5 of C99 says:

"If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined."

Remarkably, even with -Wall -Wextra -pedantic, GCC 7.3 does not throw any warnings. But some tests show that GCC does what one might expect when reading this code: cast to a signed value.

I'm just not sure whether we should add casts, or stop using the 'hack' of supplying a negative value to frame_add_to_extra_frame. Maybe we should add a frame_remove_from_extra_frame function instead. What do you think?

-Steffan

#2 lore raw

Hi

Quoted 60 lines · Steffan Karger

Hi,

src/openvpn/options.c calc_options_string_link_mtu(const struct options

Quoted 22 lines · Lev Stipakov

From: Lev Stipakov <[email protected]...>

In Visual Studio when unary minus is applied to unsigned, result is still unsigned. This means that when we use result as function formal parameter, we pass incorrect value.

Fix by adding explicit cast to signed type.

Since GCC doesn't complain (and users too :), it probably casts to signed automatically.

---
 src/openvpn/options.c | 2 +-
 src/openvpn/ssl.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
src/openvpn/options.c +0 -0
index e42029c..1927a32 100644
@@ -3509,7 +3509,7 @@ calc_options_string_link_mtu(const struct options

*o, const struct frame *frame)

src/openvpn/options.c calc_options_string_link_mtu(const struct options · line 3510

Quoted 2 lines
src/openvpn/options.c +0 -0
         struct key_type fake_kt;
         init_key_type(&fake_kt, o->ciphername, o->authname, o->keysize,

true,

src/openvpn/options.c calc_options_string_link_mtu(const struct options *o, const struct frame *frame)

Quoted 3 lines
src/openvpn/options.c +1 -1
                       false);
-        frame_add_to_extra_frame(&fake_frame, -(crypto_max_overhead()));
+        frame_add_to_extra_frame(&fake_frame,

-(int)(crypto_max_overhead()));

src/openvpn/options.c calc_options_string_link_mtu(const struct options · line 3514

Quoted 2 lines
src/openvpn/options.c +0 -0
         crypto_adjust_frame_parameters(&fake_frame, &fake_kt, o->replay,
 

cipher_kt_mode_ofb_cfb(fake_kt.cipher));

src/openvpn/options.c calc_options_string_link_mtu(const struct options · line 3515

Quoted 1 line
src/openvpn/options.c +0 -0
         frame_finalize(&fake_frame, o->ce.link_mtu_defined,

o->ce.link_mtu,

src/openvpn/ssl.c tls_session_update_crypto_params(struct

Quoted 5 lines
src/openvpn/ssl.c +0 -0
index 315303b..18b1fbd 100644
@@ -1987,7 +1987,7 @@ tls_session_update_crypto_params(struct

tls_session *session,

src/openvpn/ssl.c tls_session_update_crypto_params(struct · line 1989

Quoted 3 lines
src/openvpn/ssl.c +0 -0
     }
 
     /* Update frame parameters: undo worst-case overhead, add actual

overhead */

src/openvpn/ssl.c tls_session_update_crypto_params(struct tls_session *session,

Quoted 4 lines
src/openvpn/ssl.c +1 -1
-    frame_add_to_extra_frame(frame, -(crypto_max_overhead()));
+    frame_add_to_extra_frame(frame, -(int)(crypto_max_overhead()));
     crypto_adjust_frame_parameters(frame, &session->opt->key_type,
                                    options->replay,

packet_id_long_form);

src/openvpn/ssl.c tls_session_update_crypto_params(struct · line 1993

Quoted 1 line
src/openvpn/ssl.c +0 -0
     frame_finalize(frame, options->ce.link_mtu_defined,

options->ce.link_mtu,

Quoted 1 line

Good catch. I had to look it up, but I think this is actually undefined behaviour. 6.5 point 5 of C99 says:

Quoted 9 lines

"If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined."

Remarkably, even with -Wall -Wextra -pedantic, GCC 7.3 does not throw any warnings. But some tests show that GCC does what one might expect when reading this code: cast to a signed value.

In fact the issue here is not the unary minus, but the unsigned to signed conversion. So when there is no scope for overflow all is good. If there is overflow, unsigned->signed conversion is ill-defined -- cast doesn't fix it. In fact the cast is meaningless here (see more on that below):

Although C99 std does not seem to be explicit about unary minus of unsigned, the practice in C even before that was to subtract the number from the largest possible value and add 1: as in K&R A7.4.5 (p. 204 in my copy):

"If the operand is unsigned, the result is computed by subtracting the value from the largest value of the promoted type"

So unary minus of unsigned itself is well-defined. Actually even the unary minus of unsigned is computed using the above rule for signed:

"If the operand is signed, the result is computed by promoted operand to its unsigned type, applying -, and converting back to the signed type".!!

So what the cast achieves is a an additional iteration of conversions which gains nothing.

Quoted 5 lines

I'm just not sure whether we should add casts, or stop using the 'hack' of supplying a negative value to frame_add_to_extra_frame. Maybe we should add a frame_remove_from_extra_frame function instead. What do you think?

If the logic could be changed that should be preferred.

Selva

#3 lore raw

Hi,

More noise: a typo alert below:

Quoted 36 lines · Selva Nair

Hi

Quoted 12 lines · Steffan Karger

Hi,

Quoted 5 lines · Lev Stipakov

From: Lev Stipakov <[email protected]...>

In Visual Studio when unary minus is applied to unsigned, result is still unsigned. This means that when we use result as function formal parameter, we pass incorrect value.

Good catch. I had to look it up, but I think this is actually undefined behaviour. 6.5 point 5 of C99 says:

Quoted 9 lines

"If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined."

Remarkably, even with -Wall -Wextra -pedantic, GCC 7.3 does not throw any warnings. But some tests show that GCC does what one might expect when reading this code: cast to a signed value.

In fact the issue here is not the unary minus, but the unsigned to signed conversion. So when there is no scope for overflow all is good. If there is overflow, unsigned->signed conversion is ill-defined -- cast doesn't fix it. In fact the cast is meaningless here (see more on that below):

Although C99 std does not seem to be explicit about unary minus of unsigned, the practice in C even before that was to subtract the number from the largest possible value and add 1: as in K&R A7.4.5 (p. 204 in my copy):

Quoted 6 lines

"If the operand is unsigned, the result is computed by subtracting the value from the largest value of the promoted type"

So unary minus of unsigned itself is well-defined. Actually even the unary minus of unsigned is computed using the above rule for signed:

Typo alert: signed and unsigned inverted in the last sentence, in case anyone really read all that..

Quoted 17 lines

"If the operand is signed, the result is computed by promoted operand to its unsigned type, applying -, and converting back to the signed type".!!

So what the cast achieves is a an additional iteration of conversions which gains nothing.

Quoted 5 lines

I'm just not sure whether we should add casts, or stop using the 'hack' of supplying a negative value to frame_add_to_extra_frame. Maybe we should add a frame_remove_from_extra_frame function instead. What do you think?

If the logic could be changed that should be preferred.

Selva

#4 lore raw
In reply to Selva Nair

Hi

Quoted 18 lines · Selva Nair

In fact the issue here is not the unary minus, but the unsigned to signed conversion. So when there is no scope for overflow all is good. If there is overflow, unsigned->signed conversion is ill-defined -- cast doesn't fix it. In fact the cast is meaningless here (see more on that below):

Although C99 std does not seem to be explicit about unary minus of unsigned, the practice in C even before that was to subtract the number from the largest possible value and add 1: as in K&R A7.4.5 (p. 204 in my copy):

"If the operand is unsigned, the result is computed by subtracting the value from the largest value of the promoted type"

So unary minus of unsigned itself is well-defined. Actually even the unary minus of unsigned is computed using the above rule for signed:

Quoted 8 lines

"If the operand is signed, the result is computed by promoted operand to its unsigned type, applying -, and converting back to the signed type".!!

So what the cast achieves is a an additional iteration of conversions which gains nothing.

Ignore most of it -- I'm having really bad day and writing mostly nonsense.

Selva

#5 lore raw
In reply to Steffan Karger

Hi,

This was catched by Visual Studio. Moreover, with SDL enabled (
https://docs.microsoft.com/fi-fi/cpp/build/reference/sdl-enable-additional-security-checks?view=vs-2017
)
this warning is treated as an error.

It is probably a good idea to trigger Visual Studio build on every commit to master
(and enable SDL), have to think what would be the best way to do it. Currently
we build with VS when making PRs to openvpn-build, which we don't do that often.

I'm just not sure whether we should add casts, or stop using the 'hack'

Quoted 4 lines

of supplying a negative value to frame_add_to_extra_frame. Maybe we should add a frame_remove_from_extra_frame function instead. What do you think?

Agreed, semantically it is more clear when _add_ method adds and _remove_ method removes.

I'll add _remove_ method and change type of "increment" parameter to unsigned in both methods so that next time when we'll try to use _add_ with negative value, we'll get a warning.

Signature · 1 line
-Lev
#6 lore raw

PATCH v2 1/1 options.c: fix broken unary minus usage

From: Lev Stipakov <[email protected]...>

In Visual Studio when unary minus is applied to unsigned, result is still unsigned. This means that when we use result as function formal parameter, we pass incorrect value.

Fix by introducing frame_remove_from_extra_frame function, which makes code semantically more clear and eliminates the need in negative value and cast.

Since GCC didn't complain (and users too :), it probably performed cast to signed automatically.

---
v2: use frame_remove_from_extra_frame instead of passing negative value

 src/openvpn/crypto.c  | 2 +-
 src/openvpn/init.c    | 2 +-
 src/openvpn/mtu.h     | 8 +++++++-
 src/openvpn/options.c | 2 +-
 src/openvpn/ssl.c     | 2 +-
 5 files changed, 11 insertions(+), 5 deletions(-)
src/openvpn/crypto.c +1 -1
index 6d34acd..b1d6780 100644
@@ -722,7 +722,7 @@ crypto_adjust_frame_parameters(struct frame *frame,
 
     crypto_overhead += kt->hmac_length;
 
-    frame_add_to_extra_frame(frame, crypto_overhead);
+    frame_add_to_extra_frame(frame, (unsigned int) crypto_overhead);
 
     msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for crypto by %u bytes",
         __func__, (unsigned int) crypto_overhead);
src/openvpn/init.c +1 -1
index 52c64da..fe70175 100644
@@ -2675,7 +2675,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags)
     if (c->options.pull || c->options.mode == MODE_SERVER)
     {
         /* Account for worst-case crypto overhead before allocating buffers */
-        frame_add_to_extra_frame(&c->c2.frame, crypto_max_overhead());
+        frame_add_to_extra_frame(&c->c2.frame, (unsigned int) crypto_max_overhead());
     }
     else
     {
src/openvpn/mtu.h +7 -1
index a82154a..690eb81 100644
@@ -271,12 +271,18 @@ frame_add_to_link_mtu(struct frame *frame, const int increment)
 }
 
 static inline void
-frame_add_to_extra_frame(struct frame *frame, const int increment)
+frame_add_to_extra_frame(struct frame *frame, const unsigned int increment)
 {
     frame->extra_frame += increment;
 }
 
 static inline void
+frame_remove_from_extra_frame(struct frame *frame, const unsigned int increment)
+{
+    frame->extra_frame -= increment;
+}
+
+static inline void
 frame_add_to_extra_tun(struct frame *frame, const int increment)
 {
     frame->extra_tun += increment;
src/openvpn/options.c +1 -1
index e42029c..be47090 100644
@@ -3509,7 +3509,7 @@ calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
         struct key_type fake_kt;
         init_key_type(&fake_kt, o->ciphername, o->authname, o->keysize, true,
                       false);
-        frame_add_to_extra_frame(&fake_frame, -(crypto_max_overhead()));
+        frame_remove_from_extra_frame(&fake_frame, (unsigned int) crypto_max_overhead());
         crypto_adjust_frame_parameters(&fake_frame, &fake_kt, o->replay,
                                        cipher_kt_mode_ofb_cfb(fake_kt.cipher));
         frame_finalize(&fake_frame, o->ce.link_mtu_defined, o->ce.link_mtu,
src/openvpn/ssl.c +1 -1
index 315303b..747e176 100644
@@ -1987,7 +1987,7 @@ tls_session_update_crypto_params(struct tls_session *session,
     }
 
     /* Update frame parameters: undo worst-case overhead, add actual overhead */
-    frame_add_to_extra_frame(frame, -(crypto_max_overhead()));
+    frame_remove_from_extra_frame(frame, (unsigned int) crypto_max_overhead());
     crypto_adjust_frame_parameters(frame, &session->opt->key_type,
                                    options->replay, packet_id_long_form);
     frame_finalize(frame, options->ce.link_mtu_defined, options->ce.link_mtu,
Signature · 1 line
2.7.4
Acked-by on v2 1/1
#7 lore raw

Am 10.10.18 um 14:26 schrieb Lev Stipakov:

Quoted 9 lines

From: Lev Stipakov <[email protected]...>

In Visual Studio when unary minus is applied to unsigned, result is still unsigned. This means that when we use result as function formal parameter, we pass incorrect value.

Fix by introducing frame_remove_from_extra_frame function, which makes code semantically more clear and eliminates the need in negative value and cast.

ACK. Looks much cleaner.

#8 lore raw
In reply to Lev Stipakov

Hi,

src/openvpn/crypto.c crypto_adjust_frame_parameters(struct frame *frame, · line 725

Quoted 4 lines · Lev Stipakov
     crypto_overhead += kt->hmac_length;
src/openvpn/crypto.c +1 -1
-    frame_add_to_extra_frame(frame, crypto_overhead);
+    frame_add_to_extra_frame(frame, (unsigned int) crypto_overhead);

Even if Arne already ACKed it, I have reservations about this.

Since crypto_overhead and crypto_max_overhead() are both size_t, and frame_add_to_extra_frame() is declared to take an "unsigned int" now, this cast should not be necessary.

Unnecessary casts hide bugs and hurt my eyes...

src/openvpn/mtu.h frame_add_to_link_mtu(struct frame *frame, const int increment) · line 283

Quoted 5 lines

static inline void

src/openvpn/mtu.h +4 -0
+frame_remove_from_extra_frame(struct frame *frame, const unsigned int increment)
+{
+    frame->extra_frame -= increment;
+}

Maybe call the negative increment a "decrement" instead?

src/openvpn/options.c calc_options_string_link_mtu(const struct options *o, const struct frame *frame) · line 3512

Quoted 6 lines
src/openvpn/options.c +1 -1
@@ -3509,7 +3509,7 @@ calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
         struct key_type fake_kt;
         init_key_type(&fake_kt, o->ciphername, o->authname, o->keysize, true,
                       false);
-        frame_add_to_extra_frame(&fake_frame, -(crypto_max_overhead()));
+        frame_remove_from_extra_frame(&fake_frame, (unsigned int) crypto_max_overhead());

Same here wrt (unsigned int) cast.

Otherwise indeed much clearer.

gert

Signature · 6 lines
"If was one thing all people took for granted, was conviction that if you 
 feed honest figures into a computer, honest figures come out. Never doubted 
 it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             [email protected]...
#9 lore raw

Hi,

Quoted 3 lines

Since crypto_overhead and crypto_max_overhead() are both size_t, and frame_add_to_extra_frame() is declared to take an "unsigned int" now, this cast should not be necessary.

Visual Studio disagrees. Without explicit cast I got

Quoted 1 line

warning C4267: 'function': conversion from 'size_t' to 'const unsigned

int', possible loss of data

https://docs.microsoft.com/fi-fi/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4267?view=vs-2017

'var' : conversion from 'size_t' to 'type', possible loss of data The compiler detected a conversion from size_t to a smaller type.

Quoted 2 lines

Unnecessary casts hide bugs and hurt my eyes...

OTOH this is level 3 warning, which we have over 500. Since we'll probably change level warning to 2 and
GCC doesn't complain, I'll remove it.

Maybe call the negative increment a "decrement" instead?

Quoted 1 line

Yes.

Otherwise indeed much clearer.

Quoted 1 line

V3 is on its way.

Signature · 1 line
-Lev
#10 lore raw

Hi,

Quoted 7 lines · Lev Stipakov
Quoted 3 lines

Since crypto_overhead and crypto_max_overhead() are both size_t, and frame_add_to_extra_frame() is declared to take an "unsigned int" now, this cast should not be necessary.

Visual Studio disagrees. Without explicit cast I got

Quoted 8 lines
Quoted 1 line

warning C4267: 'function': conversion from 'size_t' to 'const unsigned

int', possible loss of data

https://docs.microsoft.com/fi-fi/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4267?view=vs-2017

'var' : conversion from 'size_t' to 'type', possible loss of data The compiler detected a conversion from size_t to a smaller type.

So, maybe "crypto_overhead" and "crypto_max_overhead()" should be changed to be just "int" here...?

For something which has a numeric value between "10-ish" and "100" (maybe), using a 64bit integer initially and then adding casts because we want to work with 32bit integers later on and not be warned about it sounds like the wrong way to tackle this...

I know that Steffan likes using size_t for "things that have a size" but I find it a bit questionable here :-)

Quoted 5 lines
Quoted 1 line

Unnecessary casts hide bugs and hurt my eyes...

OTOH this is level 3 warning, which we have over 500. Since we'll probably change level warning to 2 and
GCC doesn't complain, I'll remove it.

I'm all for fixing compiler warnings, but I hate silencing warnings with casts that serve no purpose but "silence warning". If we can fix it for real, so the compiler has nothing to warn about, this is way better.

(It might not always be possible, like const/no-const mismatch on some API functions, or struct sockaddr* madness on the socket API)

gert

Signature · 6 lines
"If was one thing all people took for granted, was conviction that if you 
 feed honest figures into a computer, honest figures come out. Never doubted 
 it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             [email protected]...
#11 lore raw

PATCH v3 1/1 options.c: fix broken unary minus usage

From: Lev Stipakov <[email protected]...>

In Visual Studio when unary minus is applied to unsigned, result is still unsigned. This means that when we use result as function formal parameter, we pass incorrect value.

Fix by introducing frame_remove_from_extra_frame(), which makes code semantically more clear and eliminates the need in negative value and cast.

Since GCC didn't complain (and users too :), it probably performed cast to signed automatically.

---
v3:
- change crypto_overhead and crypto_max_overhead() type to unsigned int to avoid additional cast or warning in Visual Studio
- rename "increment" formal paremeter to "decrement"

v2:
- use new frame_remove_from_extra_frame() instead of
passing negative value

 src/openvpn/crypto.c  | 6 +++---
 src/openvpn/crypto.h  | 2 +-
 src/openvpn/mtu.h     | 8 +++++++-
 src/openvpn/options.c | 2 +-
 src/openvpn/ssl.c     | 2 +-
 5 files changed, 13 insertions(+), 7 deletions(-)
src/openvpn/crypto.c +3 -3
index 6d34acd..8416b89 100644
@@ -700,7 +700,7 @@ crypto_adjust_frame_parameters(struct frame *frame,
                                bool packet_id,
                                bool packet_id_long_form)
 {
-    size_t crypto_overhead = 0;
+    unsigned int crypto_overhead = 0;
 
     if (packet_id)
     {
@@ -725,10 +725,10 @@ crypto_adjust_frame_parameters(struct frame *frame,
     frame_add_to_extra_frame(frame, crypto_overhead);
 
     msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for crypto by %u bytes",
-        __func__, (unsigned int) crypto_overhead);
+        __func__, crypto_overhead);
 }
 
-size_t
+unsigned int
 crypto_max_overhead(void)
 {
     return packet_id_size(true) + OPENVPN_MAX_IV_LENGTH
src/openvpn/crypto.h +1 -1
index 263725d..1d7f4c5 100644
@@ -418,7 +418,7 @@ void crypto_adjust_frame_parameters(struct frame *frame,
                                     bool packet_id_long_form);
 
 /** Return the worst-case OpenVPN crypto overhead (in bytes) */
-size_t crypto_max_overhead(void);
+unsigned int crypto_max_overhead(void);
 
 /* Minimum length of the nonce used by the PRNG */
 #define NONCE_SECRET_LEN_MIN 16
src/openvpn/mtu.h +7 -1
index a82154a..cfa8d2f 100644
@@ -271,12 +271,18 @@ frame_add_to_link_mtu(struct frame *frame, const int increment)
 }
 
 static inline void
-frame_add_to_extra_frame(struct frame *frame, const int increment)
+frame_add_to_extra_frame(struct frame *frame, const unsigned int increment)
 {
     frame->extra_frame += increment;
 }
 
 static inline void
+frame_remove_from_extra_frame(struct frame *frame, const unsigned int decrement)
+{
+    frame->extra_frame -= decrement;
+}
+
+static inline void
 frame_add_to_extra_tun(struct frame *frame, const int increment)
 {
     frame->extra_tun += increment;
src/openvpn/options.c +1 -1
index e42029c..3ce620a 100644
@@ -3509,7 +3509,7 @@ calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
         struct key_type fake_kt;
         init_key_type(&fake_kt, o->ciphername, o->authname, o->keysize, true,
                       false);
-        frame_add_to_extra_frame(&fake_frame, -(crypto_max_overhead()));
+        frame_remove_from_extra_frame(&fake_frame, crypto_max_overhead());
         crypto_adjust_frame_parameters(&fake_frame, &fake_kt, o->replay,
                                        cipher_kt_mode_ofb_cfb(fake_kt.cipher));
         frame_finalize(&fake_frame, o->ce.link_mtu_defined, o->ce.link_mtu,
src/openvpn/ssl.c +1 -1
index 315303b..9e2fd94 100644
@@ -1987,7 +1987,7 @@ tls_session_update_crypto_params(struct tls_session *session,
     }
 
     /* Update frame parameters: undo worst-case overhead, add actual overhead */
-    frame_add_to_extra_frame(frame, -(crypto_max_overhead()));
+    frame_remove_from_extra_frame(frame, crypto_max_overhead());
     crypto_adjust_frame_parameters(frame, &session->opt->key_type,
                                    options->replay, packet_id_long_form);
     frame_finalize(frame, options->ce.link_mtu_defined, options->ce.link_mtu,
Signature · 1 line
2.7.4
Acked-by on v3 1/1
#12 lore raw

Thanks for bearing with me :-) - code looks correct, passes all t_client tests (which should trigger the increment/decrement code paths). Bonus points for *removing* a cast ;-))

Your patch has been applied to the master and release/2.4 branch (bugfix).

commit ed31cf2ab718d879615dea81e6a17d26537ab43a (master) commit 62eb234c810533c7ea13d8a9faa28eebe07f2e82 (release/2.4)

Author: Lev Stipakov
Date:   Thu Oct 11 14:51:42 2018 +0300
     options.c: fix broken unary minus usage

     Signed-off-by: Lev Stipakov <[email protected]...>
     Acked-by: Gert Doering <[email protected]...>
     Message-Id: <[email protected]...>
     URL: https://www.mail-archive.com/[email protected]/msg17739.html
     Signed-off-by: Gert Doering <[email protected]...>

--
kind regards,

Gert Doering

#13 lore raw
In reply to Gert Doering

Hi,

Quoted 20 lines · Gert Doering
Quoted 7 lines · Lev Stipakov
Quoted 3 lines

Since crypto_overhead and crypto_max_overhead() are both size_t, and frame_add_to_extra_frame() is declared to take an "unsigned int" now, this cast should not be necessary.

Visual Studio disagrees. Without explicit cast I got

Quoted 8 lines
Quoted 1 line

warning C4267: 'function': conversion from 'size_t' to 'const unsigned

int', possible loss of data

https://docs.microsoft.com/fi-fi/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4267?view=vs-2017

'var' : conversion from 'size_t' to 'type', possible loss of data The compiler detected a conversion from size_t to a smaller type.

So, maybe "crypto_overhead" and "crypto_max_overhead()" should be changed to be just "int" here...?

Quoted 7 lines

For something which has a numeric value between "10-ish" and "100" (maybe), using a 64bit integer initially and then adding casts because we want to work with 32bit integers later on and not be warned about it sounds like the wrong way to tackle this...

I know that Steffan likes using size_t for "things that have a size" but I find it a bit questionable here :-)

So the underlying problem is that "further down" used int to store sizes, but since that just is the way it is and we shouldn't pull in refactoring the code base for each small change, I would say either make both 'int', or make both 'size_t', but without changing the types of struct frame itself. I of course prefer the latter ;-)

-Steffan

#14 lore raw

Hi,

Quoted 8 lines · Steffan Karger
Quoted 2 lines

I know that Steffan likes using size_t for "things that have a size" but I find it a bit questionable here :-)

So the underlying problem is that "further down" used int to store sizes, but since that just is the way it is and we shouldn't pull in refactoring the code base for each small change, I would say either make both 'int', or make both 'size_t', but without changing the types of struct frame itself. I of course prefer the latter ;-)

Adding or substracting a size_t from frame->extra_frame (which is an int) will quite likely cause the same warning again... so I'd argue for "make it all int, and be happy with it foreverafter" :-)

(And possibly revisit our use of size_t... *cough*)

gert

Signature · 6 lines
"If was one thing all people took for granted, was conviction that if you 
 feed honest figures into a computer, honest figures come out. Never doubted 
 it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             [email protected]...
#15 lore raw
Quoted 4 lines · Gert Doering
Quoted 3 lines · Steffan Karger
Quoted 2 lines

I know that Steffan likes using size_t for "things that have a size" but I find it a bit questionable here :-)

Quoted 8 lines
Quoted 5 lines

So the underlying problem is that "further down" used int to store sizes, but since that just is the way it is and we shouldn't pull in refactoring the code base for each small change, I would say either make both 'int', or make both 'size_t', but without changing the types of struct frame itself. I of course prefer the latter ;-)

Adding or substracting a size_t from frame->extra_frame (which is an int) will quite likely cause the same warning again...

I don't think so, because at that level, you'll be adding/subtracting either "int + int" or "int + size_t", which are equally likely to cause overflows. Only that signed overflows are not only not what you want, but also undefined behaviour.

But well, as I said, I'm fine with both in this case. It will effectively not change any logic anyway.

-Steffan