Discussion:
[std-proposals] more security concerns
Daniel Gutson
2018-09-28 11:13:53 UTC
Permalink
Again, on the DSE related optimizations.

I'm at the Ekoparty where I will show a presentation about security
vulnerabilities caused by compiler optimizations. The subject is more and
more serious (e.g. [1]).

I want to propose to allow [[nodiscard]] in individual expressions, such as
calls to memset(), std::fill_n, and assignments (DSE happens with both
memory and registers).

Ideas? Co-authors?
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-0NqfbqeOhhH1YiVGxDRVPv7COKNqge3mLu8UE8SgcXNw%40mail.gmail.com.
Andrew Giese
2018-09-28 13:32:28 UTC
Permalink
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/

If gcc poison were standardized in some fashion, you could write your own
wrappers to those functions with all the [[nodiscard]] you might want.

Control in that case is a little less granular, indeed. Probably if you're
writing [[nodiscard]] on a per-expression basis you are not discarding the
result already.

Regards
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com.
Daniel Gutson
2018-09-28 13:36:27 UTC
Permalink
Yeah. But please note that this is not only for function calls.

void f()
{
int secret;
....
secret = 0; //removed due to DSE
}

If I declare secret as volatile or write 0s to its address I may prevent
the compiler to use a register impacting in performance. That's why I want
to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your own
wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if you're
writing [[nodiscard]] on a per-expression basis you are not discarding the
result already.
Regards
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-1DpAUkYDVyNmP5H49XyNVDq5_T6UkEVaQGMGA0YEhNGw%40mail.gmail.com.
f***@gmail.com
2018-09-28 14:14:20 UTC
Permalink
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
So meaning would be different.
In that respect, another attribute name might be better.

Also, it is already possible (but cumbersome) to implement already without
volatile:
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}

I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may prevent
the compiler to use a register impacting in performance. That's why I want
to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your own
wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org.
Daniel Gutson
2018-09-28 14:17:56 UTC
Permalink
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
I'm proposing using [[nodiscard]] for statements rather than for
declarations.
That being said, it would be placed in the function call statement. I want
the compiler to still do DSE where appropriate and at the same time allow
the programmer to thoughtfully prevent it.


So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already without
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may prevent
the compiler to use a register impacting in performance. That's why I want
to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your
own wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-1tpJj3bSzHgD%3DpxWD2eVokRX3ST2QE-oF6M8z1%3DDTEoQ%40mail.gmail.com.
Daniel Gutson
2018-09-28 14:20:49 UTC
Permalink
(Clarification)
Post by Daniel Gutson
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
In THIS proposal....
Post by Daniel Gutson
I'm proposing using [[nodiscard]] for statements rather than
..in addition to...

for declarations.
That being said, it would be placed in the function call statement. I want
Post by Daniel Gutson
the compiler to still do DSE where appropriate and at the same time allow
the programmer to thoughtfully prevent it.
So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may prevent
the compiler to use a register impacting in performance. That's why I want
to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your
own wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-1rSKBc6aQh%2BZo7imJb8_1741RPuL0VyyByTcD8zHT_6Q%40mail.gmail.com.
f***@gmail.com
2018-09-28 14:36:36 UTC
Permalink
I completely understood what you meant, and yes what you are proposing is
compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).

Also, after some thinking, in this case, the goal is not to force the last
assignment, but to force the last value of the variable, wherever the
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
of the object:

void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it becomes
valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could* be
accessed afterwards.
Post by Daniel Gutson
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
I'm proposing using [[nodiscard]] for statements rather than for
declarations.
That being said, it would be placed in the function call statement. I want
the compiler to still do DSE where appropriate and at the same time allow
the programmer to thoughtfully prevent it.
So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may prevent
the compiler to use a register impacting in performance. That's why I want
to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your
own wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org.
Daniel Gutson
2018-09-28 14:50:41 UTC
Permalink
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing is
compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the last
assignment, but to force
I just wanted to give a way to the programmer to tell the compiler that the
statement is important. Later, the compiler may just warn that it would
remove the statement (so the programmer has to look for another mean) or
honor the request by not removing anything (thus impacting in the final
binary).
Post by f***@gmail.com
the last value of the variable, wherever the variable is, even if the
variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it becomes
valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could* be
accessed afterwards.
Post by Daniel Gutson
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
I'm proposing using [[nodiscard]] for statements rather than for
declarations.
That being said, it would be placed in the function call statement. I
want the compiler to still do DSE where appropriate and at the same time
allow the programmer to thoughtfully prevent it.
So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may
prevent the compiler to use a register impacting in performance. That's why
I want to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your
own wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3rNrze-AUW-FNy6S_FRdWt78LGJyDzDGQPXqsbgHnDoQ%40mail.gmail.com.
Andrew Giese
2018-09-28 15:11:08 UTC
Permalink
I think the primary opposition will come from the fact that DSE is, for the
moment, an implementation detail of the compiler. So, to have this
standardized, we might also need to standardize DSE.

The name of the attribute will also be endlessly debated I'm sure. The
existing attributes are about informing compilers and programmers of
program correctness (e.g., it's correct to fall through a case label), and
this one is only about compiler optimization. Reusing [[nodiscard]] in this
fashion might be argued to be disruptive, so we need to be ready for that.
On the other hand, the committee likes to avoid new reserved words, so
[[nodiscard]] may be preferable.

Regards
Andy
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing is
compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the
last assignment, but to force
I just wanted to give a way to the programmer to tell the compiler that
the statement is important. Later, the compiler may just warn that it would
remove the statement (so the programmer has to look for another mean) or
honor the request by not removing anything (thus impacting in the final
binary).
Post by f***@gmail.com
the last value of the variable, wherever the variable is, even if the
variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it becomes
valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could* be
accessed afterwards.
Post by Daniel Gutson
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about
forcing the compiler to keep the value, but instead to emit a warning if
the user doesn't use the value.
I'm proposing using [[nodiscard]] for statements rather than for
declarations.
That being said, it would be placed in the function call statement. I
want the compiler to still do DSE where appropriate and at the same time
allow the programmer to thoughtfully prevent it.
So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may
prevent the compiler to use a register impacting in performance. That's why
I want to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your
own wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it,
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3rNrze-AUW-FNy6S_FRdWt78LGJyDzDGQPXqsbgHnDoQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3rNrze-AUW-FNy6S_FRdWt78LGJyDzDGQPXqsbgHnDoQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4Mo6Cn8rAw%2BsukXyv%3DpsExWBjBehr%2B2G4SDB1sSvm-Rw%40mail.gmail.com.
Daniel Gutson
2018-09-28 15:21:42 UTC
Permalink
Post by Andrew Giese
I think the primary opposition will come from the fact that DSE is, for
the moment, an implementation detail of the compiler. So, to have this
standardized, we might also need to standardize DSE.
I gently disagree: attributes are exactly targetted to QoI and compiler
implementations, they are ignorable, and they may target either
optimizations or diagnostics. Even the original (current) [[nodiscard]]
targets diagnostics; I'm proposing to extend it to other uses.
[[nodiscard]] used in statements could perfectly target the diagnostics
subsystem as well, but that will be QoI (it could either do nothing, or
prevent discarding).
In no way I pretend to standardize optimizations in general nor DSE in
particular. Otherwise then CSE will arrive, etc.
Post by Andrew Giese
The name of the attribute will also be endlessly debated I'm sure. The
existing attributes are about informing compilers and programmers of
program correctness (e.g., it's correct to fall through a case label), and
this one is only about compiler optimization. Reusing [[nodiscard]] in this
fashion might be argued to be disruptive, so we need to be ready for that.
On the other hand, the committee likes to avoid new reserved words, so
[[nodiscard]] may be preferable.
Regards
Andy
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing
is compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the
last assignment, but to force
I just wanted to give a way to the programmer to tell the compiler that
the statement is important. Later, the compiler may just warn that it would
remove the statement (so the programmer has to look for another mean) or
honor the request by not removing anything (thus impacting in the final
binary).
Post by f***@gmail.com
the last value of the variable, wherever the variable is, even if the
variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it becomes
valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could* be
accessed afterwards.
Post by Daniel Gutson
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about
forcing the compiler to keep the value, but instead to emit a warning if
the user doesn't use the value.
I'm proposing using [[nodiscard]] for statements rather than for
declarations.
That being said, it would be placed in the function call statement. I
want the compiler to still do DSE where appropriate and at the same time
allow the programmer to thoughtfully prevent it.
So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may
prevent the compiler to use a register impacting in performance. That's why
I want to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write
your own wrappers to those functions with all the [[nodiscard]] you might
want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it,
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3rNrze-AUW-FNy6S_FRdWt78LGJyDzDGQPXqsbgHnDoQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3rNrze-AUW-FNy6S_FRdWt78LGJyDzDGQPXqsbgHnDoQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4Mo6Cn8rAw%2BsukXyv%3DpsExWBjBehr%2B2G4SDB1sSvm-Rw%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4Mo6Cn8rAw%2BsukXyv%3DpsExWBjBehr%2B2G4SDB1sSvm-Rw%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-2Bmpf6LM2b5MJtBtkSRtDOgFWCMM%3DMqMrviETNyRhN-A%40mail.gmail.com.
Andrew Giese
2018-09-28 15:37:04 UTC
Permalink
All good points. Either way, I'm in favor of it.
El vie., 28 de sep. de 2018 a la(s) 12:11, Andrew Giese (
Post by Andrew Giese
I think the primary opposition will come from the fact that DSE is, for
the moment, an implementation detail of the compiler. So, to have this
standardized, we might also need to standardize DSE.
I gently disagree: attributes are exactly targetted to QoI and compiler
implementations, they are ignorable, and they may target either
optimizations or diagnostics. Even the original (current) [[nodiscard]]
targets diagnostics; I'm proposing to extend it to other uses.
[[nodiscard]] used in statements could perfectly target the diagnostics
subsystem as well, but that will be QoI (it could either do nothing, or
prevent discarding).
In no way I pretend to standardize optimizations in general nor DSE in
particular. Otherwise then CSE will arrive, etc.
Post by Andrew Giese
The name of the attribute will also be endlessly debated I'm sure. The
existing attributes are about informing compilers and programmers of
program correctness (e.g., it's correct to fall through a case label), and
this one is only about compiler optimization. Reusing [[nodiscard]] in this
fashion might be argued to be disruptive, so we need to be ready for that.
On the other hand, the committee likes to avoid new reserved words, so
[[nodiscard]] may be preferable.
Regards
Andy
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing
is compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the
last assignment, but to force
I just wanted to give a way to the programmer to tell the compiler that
the statement is important. Later, the compiler may just warn that it would
remove the statement (so the programmer has to look for another mean) or
honor the request by not removing anything (thus impacting in the final
binary).
Post by f***@gmail.com
the last value of the variable, wherever the variable is, even if the
variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it
becomes valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could*
be accessed afterwards.
Post by Daniel Gutson
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about
forcing the compiler to keep the value, but instead to emit a warning if
the user doesn't use the value.
I'm proposing using [[nodiscard]] for statements rather than for
declarations.
That being said, it would be placed in the function call statement. I
want the compiler to still do DSE where appropriate and at the same time
allow the programmer to thoughtfully prevent it.
So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may
prevent the compiler to use a register impacting in performance. That's why
I want to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write
your own wrappers to those functions with all the [[nodiscard]] you might
want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it,
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it,
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3rNrze-AUW-FNy6S_FRdWt78LGJyDzDGQPXqsbgHnDoQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3rNrze-AUW-FNy6S_FRdWt78LGJyDzDGQPXqsbgHnDoQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4Mo6Cn8rAw%2BsukXyv%3DpsExWBjBehr%2B2G4SDB1sSvm-Rw%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4Mo6Cn8rAw%2BsukXyv%3DpsExWBjBehr%2B2G4SDB1sSvm-Rw%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-2Bmpf6LM2b5MJtBtkSRtDOgFWCMM%3DMqMrviETNyRhN-A%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-2Bmpf6LM2b5MJtBtkSRtDOgFWCMM%3DMqMrviETNyRhN-A%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC54sTj6XV0CdD9KdZ0dt%3D8M%3DoG_cngOKq%3DKPoNsGuegng%40mail.gmail.com.
Daniel Gutson
2018-10-07 04:44:14 UTC
Permalink
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing is
compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the last
assignment, but to force the last value of the variable, wherever the
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it becomes
valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could* be
accessed afterwards.
Actually I would like to tell the compiler that the object should NOT be
accessible afterwards.
Additionally I would like to reuse the existing attribute name, though this
is of least importance now.
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
I'm proposing using [[nodiscard]] for statements rather than for
declarations.
That being said, it would be placed in the function call statement. I
want the compiler to still do DSE where appropriate and at the same time
allow the programmer to thoughtfully prevent it.
So meaning would be different.
Post by f***@gmail.com
In that respect, another attribute name might be better.
Also, it is already possible (but cumbersome) to implement already
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
I would really like an attribute for that, though.
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
If I declare secret as volatile or write 0s to its address I may
prevent the compiler to use a register impacting in performance. That's why
I want to use the attribute here too.
Post by Andrew Giese
I like the idea.
Function poisoning might also serve your needs. E.g.,
https://www.fluentcpp.com/2018/09/04/function-poisoning-in-cpp/
If gcc poison were standardized in some fashion, you could write your
own wrappers to those functions with all the [[nodiscard]] you might want.
Control in that case is a little less granular, indeed. Probably if
you're writing [[nodiscard]] on a per-expression basis you are not
discarding the result already.
Regards
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAO8_tC4kNZ6s-xMXo69n1D3dbOMkqt0fjLU44Uq5TfABp17hQQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/94d79dd7-ba3b-4bf8-91ed-e5dc02b33670%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c71e2ca9-c5f4-4699-b2c1-b23245eef683%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3RRFoPYsyyQAX0w0eshYRytoes00VkoDPLrOPjWjjv3A%40mail.gmail.com.
f***@gmail.com
2018-10-07 09:17:52 UTC
Permalink
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing is
compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the
last assignment, but to force the last value of the variable, wherever the
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it becomes
valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could* be
accessed afterwards.
Actually I would like to tell the compiler that the object should NOT be
accessible afterwards.
What I said is not "the compiler makes the object accessible", but
"whatever the compiler will do, the object will remain accessible somehow,
and so the correctness of the whole program depends on the last value not
being discarded".

Your view is also correct, but a bit more magic: when this "destroy all the
places where the object is" is performed? (the right answer is: just after
its destructor is called)
While in what I propose, it is done more explicitly when the last value is
assigned.

But both are good. It's just a matter of taste at this point.

However, your first proposal doesn't work that well: ok you tell the
compiler to keep the assignment. But which location is used for this
assignment? All of them? The last one? The main one? A new one?
And if you start standardizing which location should be assigned, then
you're not talking about expressions anymore, but about objects. So
attributes on expressions is not the right tool for you.
Post by Daniel Gutson
Additionally I would like to reuse the existing attribute name, though
this is of least importance now.
Here, I completely disagree. It should not be an already existing attribute
name unless the feature is close enough to the original attribute.
And the new meaning you proposed is (at least for me) too far from the
original, and is misleading.

An attribute is not a keyword, it is easy to create new ones (easier than
repurposing an old one?).
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org.
Daniel Gutson
2018-10-07 14:47:23 UTC
Permalink
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing
is compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the
last assignment, but to force the last value of the variable, wherever the
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it becomes
valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could* be
accessed afterwards.
Actually I would like to tell the compiler that the object should NOT be
accessible afterwards.
What I said is not "the compiler makes the object accessible", but
"whatever the compiler will do, the object will remain accessible somehow,
and so the correctness of the whole program depends on the last value not
being discarded".
Your view is also correct, but a bit more magic: when this "destroy all
the places where the object is" is performed? (the right answer is: just
after its destructor is called)
While in what I propose, it is done more explicitly when the last value is
assigned.
But both are good. It's just a matter of taste at this point.
However, your first proposal doesn't work that well: ok you tell the
compiler to keep the assignment. But which location is used for this
assignment? All of them? The last one? The main one? A new one?
And if you start standardizing which location should be assigned, then
you're not talking about expressions anymore, but about objects. So
attributes on expressions is not the right tool for you.
Post by Daniel Gutson
Additionally I would like to reuse the existing attribute name, though
this is of least importance now.
Here, I completely disagree.
Ok let's not discuss this.

It should not be an already existing attribute name unless the feature is
Post by f***@gmail.com
close enough to the original attribute.
And the new meaning you proposed is (at least for me) too far from the
original, and is misleading.
An attribute is not a keyword, it is easy to create new ones (easier than
repurposing an old one?).
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-1cyt1gnCvvtrE%2BJOW0s%3Dwab%3D0eU1APYzdrwejxjqc1zg%40mail.gmail.com.
Andrew Giese
2018-10-08 19:02:59 UTC
Permalink
What about using [[nodiscard]] as a null-statement?

Similar to how [[fallthrough]] is a null statement intended to indicate to
the compiler and reader that the fallthrough is intentional, a
[[nodiscard]] after an assignment or a memset should indicate that the
previous statement was intentional and should not be discarded.

e.g.

memset(password, 0, PASSWORD_SIZE);
[[nodiscard]]; // intentionally store before a free
free(password);
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing
is compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the
last assignment, but to force the last value of the variable, wherever the
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it
becomes valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could*
be accessed afterwards.
Actually I would like to tell the compiler that the object should NOT be
accessible afterwards.
What I said is not "the compiler makes the object accessible", but
"whatever the compiler will do, the object will remain accessible somehow,
and so the correctness of the whole program depends on the last value not
being discarded".
Your view is also correct, but a bit more magic: when this "destroy all
the places where the object is" is performed? (the right answer is: just
after its destructor is called)
While in what I propose, it is done more explicitly when the last value
is assigned.
But both are good. It's just a matter of taste at this point.
However, your first proposal doesn't work that well: ok you tell the
compiler to keep the assignment. But which location is used for this
assignment? All of them? The last one? The main one? A new one?
And if you start standardizing which location should be assigned, then
you're not talking about expressions anymore, but about objects. So
attributes on expressions is not the right tool for you.
Post by Daniel Gutson
Additionally I would like to reuse the existing attribute name, though
this is of least importance now.
Here, I completely disagree.
Ok let's not discuss this.
It should not be an already existing attribute name unless the feature is
Post by f***@gmail.com
close enough to the original attribute.
And the new meaning you proposed is (at least for me) too far from the
original, and is misleading.
An attribute is not a keyword, it is easy to create new ones (easier than
repurposing an old one?).
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c35b213e-cbfd-41e2-a8dd-e5cf93343b8c%40isocpp.org.
m***@gmail.com
2018-10-09 00:38:21 UTC
Permalink
That could be easily broken if someone replaced memset() with another
super_memset() function or similar which did more than one write. How would
the compiler know which write inside of the memset() function it has to
keep? Would it only work for memset and assignments? I don't like the idea
of an attribute that only works for memset() but not other functions.
Post by Andrew Giese
What about using [[nodiscard]] as a null-statement?
Similar to how [[fallthrough]] is a null statement intended to indicate to
the compiler and reader that the fallthrough is intentional, a
[[nodiscard]] after an assignment or a memset should indicate that the
previous statement was intentional and should not be discarded.
e.g.
memset(password, 0, PASSWORD_SIZE);
[[nodiscard]]; // intentionally store before a free
free(password);
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/bf24037e-142a-4730-84e0-1886f6235e45%40isocpp.org.
Andrew Giese
2018-10-09 01:55:03 UTC
Permalink
Post by m***@gmail.com
That could be easily broken if someone replaced memset() with another
super_memset() function or similar which did more than one write
I'm not sure it's any more easy to break than [[fallthrough]] is by, say,
the introduction of a new case label that shouldn't be fallen into (which
has bitten me before).

How would the compiler know which write inside of the memset() function it
Post by m***@gmail.com
has to keep?
I think all I'd want it to mean is that the compiler should, under no
circumstances, discard the statement directly above the [[nodiscard]] null
statement. That is, it's a signal of intent that "I want all the side
effects of the above statement to happen". Devs must be careful during
refactoring. Fortunately, whether the store was discarded or not can likely
be tested via unit testing.

I'm no compiler expert, so I don't know the practicalities of something
like this.

Regards,
-Andy
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a3de61e-037c-48cc-8704-e26ca2ec1213%40isocpp.org.
Daniel Gutson
2018-10-09 02:24:37 UTC
Permalink
Post by m***@gmail.com
That could be easily broken if someone replaced memset() with another
super_memset() function or similar which did more than one write. How would
the compiler know which write inside of the memset() function it has to
keep? Would it only work for memset and assignments? I don't like the idea
of an attribute that only works for memset() but not other functions.
That's why I'm struggling to explain that this attribute is statement-wise
rather than for annotating function *calls* only
Post by m***@gmail.com
Post by Andrew Giese
What about using [[nodiscard]] as a null-statement?
Similar to how [[fallthrough]] is a null statement intended to indicate
to the compiler and reader that the fallthrough is intentional, a
[[nodiscard]] after an assignment or a memset should indicate that the
previous statement was intentional and should not be discarded.
e.g.
memset(password, 0, PASSWORD_SIZE);
[[nodiscard]]; // intentionally store before a free
free(password);
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/bf24037e-142a-4730-84e0-1886f6235e45%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/bf24037e-142a-4730-84e0-1886f6235e45%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-1nTmSAMa4zOg5tAbm%3DrspsbMv0Z_sBfpTTHHvauJKiJg%40mail.gmail.com.
f***@gmail.com
2018-10-09 08:18:34 UTC
Permalink
Post by Daniel Gutson
Post by m***@gmail.com
That could be easily broken if someone replaced memset() with another
super_memset() function or similar which did more than one write. How would
the compiler know which write inside of the memset() function it has to
keep? Would it only work for memset and assignments? I don't like the idea
of an attribute that only works for memset() but not other functions.
That's why I'm struggling to explain that this attribute is statement-wise
rather than for annotating function *calls* only
Your very first example is not suited for an attribute on a statement, but
for an attribute on the object itself because you don't know (and will
never know) where the object is (in register? in memory? both?) and on
which location the last assignment is done.
Even if you could force the assignment both in register and in memory, are
you sure the assignment in register has overridden the right register?
So enforcing that the last assignment is done gives you almost nothing in
that case (That's why I proposed the [[undead]] attribute, but alternatives
are fine).

However, for other purposes I think it's fine (the memset example on heap
memory) and here I completely agree that an attribute on the statement is
the right way to do (I just disagree on the name of of the attribute
because I find it misleading).
I also want to mention here, that it is already possible to do it with
inline asm (not standard).
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e7edc1e3-a9b3-421c-a72f-623d6c34b104%40isocpp.org.
Daniel Gutson
2018-10-09 10:41:06 UTC
Permalink
Post by f***@gmail.com
Post by Daniel Gutson
Post by m***@gmail.com
That could be easily broken if someone replaced memset() with another
super_memset() function or similar which did more than one write. How would
the compiler know which write inside of the memset() function it has to
keep? Would it only work for memset and assignments? I don't like the idea
of an attribute that only works for memset() but not other functions.
That's why I'm struggling to explain that this attribute is
statement-wise rather than for annotating function *calls* only
Your very first example is not suited for an attribute on a statement, but
for an attribute on the object itself because you don't know (and will
never know) where the object is (in register? in memory? both?) and on
which location the last assignment is done.
Even if you could force the assignment both in register and in memory, are
you sure the assignment in register has overridden the right register?
Are you saying that the object may undergo internal copies for optimization
purposes (e.g. if it is in a register it may be copied to other registers
as a temporal)? It could also be arithmetically operated in other registers
which would still turn it recoverable by applying the reverse operation.
Hm. Is that what you are saying?

So enforcing that the last assignment is done gives you almost nothing in
Post by f***@gmail.com
that case (That's why I proposed the [[undead]] attribute, but alternatives
are fine).
However, for other purposes I think it's fine (the memset example on heap
memory) and here I completely agree that an attribute on the statement is
the right way to do (I just disagree on the name of of the attribute
because I find it misleading).
I also want to mention here, that it is already possible to do it with
inline asm (not standard).
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e7edc1e3-a9b3-421c-a72f-623d6c34b104%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e7edc1e3-a9b3-421c-a72f-623d6c34b104%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-0-p7rOo3MYrfa%2Bx_zc21h58fZb_Qt5a1g6ocasCqyJXw%40mail.gmail.com.
f***@gmail.com
2018-10-09 12:24:32 UTC
Permalink
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by m***@gmail.com
That could be easily broken if someone replaced memset() with another
super_memset() function or similar which did more than one write. How would
the compiler know which write inside of the memset() function it has to
keep? Would it only work for memset and assignments? I don't like the idea
of an attribute that only works for memset() but not other functions.
That's why I'm struggling to explain that this attribute is
statement-wise rather than for annotating function *calls* only
Your very first example is not suited for an attribute on a statement,
but for an attribute on the object itself because you don't know (and will
never know) where the object is (in register? in memory? both?) and on
which location the last assignment is done.
Even if you could force the assignment both in register and in memory,
are you sure the assignment in register has overridden the right register?
Are you saying that the object may undergo internal copies for
optimization purposes (e.g. if it is in a register it may be copied to
other registers as a temporal)? It could also be arithmetically operated in
other registers which would still turn it recoverable by applying the
reverse operation.
Hm. Is that what you are saying?
Yes for the first, no (but maybe yes) for the second:
Yes the compiler might duplicate the object in register for optimizations
purposes (eg: as a consequence of the SSA form). And yes, those registers
might outilive the function call (callee-saved vs caller-saved).
Actually, it might be even worse: a compiler can put you local object in
register, and because of the register pressure, the compiler spills your
object off to the stack, at a different place.

For your second point, I didn't think about it yet. So I didn't take it
into consideration when I proposed the [[undead]] attribute. But if your
goal is security, then you would also need to take into consideration this.
Let's imagine an attribute [[secret]].
Every object marked as [[secret]] will be cleaned before function exit.
This cleaning means set to zero every location that still contains the
object (known to the compiler).
Also, in order to not deduce the secret from other temporaries, any value
depending on a [[secret]] object is also marked implicitly as [[secret]].

This does not address cache persistency, but it can be covered if the
[[secret]] can take an optional argument to ensure cache lines related to
this object are flushed (done by the compiler).

With this, you start to have a pretty strong security plan for stack
objects. But the heap objects cannot be marked as secret. So for that,
maybe you could mark the delete statement as [[secret]] and let the
compiler do the same thing for heap objects.
And also, a [[secret]] reference would need mark every dependant objects as
[[secret]], but the referenced object itself would not be cleaned.
Here I'm just throwing ideas into the wild, but I think you get the idea.

All in all, I think it is possible to improve security with such
attributes, but I don't think an attribute on statements is the right way.
Post by Daniel Gutson
So enforcing that the last assignment is done gives you almost nothing in
Post by f***@gmail.com
that case (That's why I proposed the [[undead]] attribute, but alternatives
are fine).
However, for other purposes I think it's fine (the memset example on heap
memory) and here I completely agree that an attribute on the statement is
the right way to do (I just disagree on the name of of the attribute
because I find it misleading).
I also want to mention here, that it is already possible to do it with
inline asm (not standard).
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e7edc1e3-a9b3-421c-a72f-623d6c34b104%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e7edc1e3-a9b3-421c-a72f-623d6c34b104%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f5b06d59-bfc0-491b-b553-aca1c1050ee1%40isocpp.org.
Miguel Ojeda
2018-10-09 12:41:57 UTC
Permalink
Hi Florian,
For your second point, I didn't think about it yet. So I didn't take it into consideration when I proposed the [[undead]] attribute. But if your goal is security, then you would also need to take into consideration this.
Let's imagine an attribute [[secret]].
Every object marked as [[secret]] will be cleaned before function exit.
This cleaning means set to zero every location that still contains the object (known to the compiler).
This sounds very similar to secure_val, but as a variable attribute.
Also, in order to not deduce the secret from other temporaries, any value depending on a [[secret]] object is also marked implicitly as [[secret]].
This does not address cache persistency, but it can be covered if the [[secret]] can take an optional argument to ensure cache lines related to this object are flushed (done by the compiler).
With this, you start to have a pretty strong security plan for stack objects. But the heap objects cannot be marked as secret. So for that, maybe you could mark the delete statement as [[secret]] and let the compiler do the same thing for heap objects.
I would say users should not care where or how the value is stored.
Having to mark delete statements with an attribute seems odd. As a
user, I would simply prefer to be able to mark my type T with
[[secret]] and then *that* could be put into the heap. That is the
reason I went for a template, because it looked natural to wrap values
with it:

std::secure_val<int> my_very_secret_number;
std::secure_val<char [N]> my_private_key;

etc.
And also, a [[secret]] reference would need mark every dependant objects as [[secret]], but the referenced object itself would not be cleaned.
Here I'm just throwing ideas into the wild, but I think you get the idea.
All in all, I think it is possible to improve security with such attributes, but I don't think an attribute on statements is the right way.
Indeed, I think a better idea is to work on the storage side, not on
the statement level.

Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANiq72kBPp9uONTPvC7L9n8%2BrtnXtE12MM_YJQDw1JsbVQ9frA%40mail.gmail.com.
f***@gmail.com
2018-10-09 12:56:29 UTC
Permalink
Post by Miguel Ojeda
Hi Florian,
Post by f***@gmail.com
For your second point, I didn't think about it yet. So I didn't take it
into consideration when I proposed the [[undead]] attribute. But if your
goal is security, then you would also need to take into consideration this.
Post by f***@gmail.com
Let's imagine an attribute [[secret]].
Every object marked as [[secret]] will be cleaned before function exit.
This cleaning means set to zero every location that still contains the
object (known to the compiler).
This sounds very similar to secure_val, but as a variable attribute.
Yes it is similar. But I think attribute is more appropriate because those
security issues are not about C++: in order to read a destroyed value, you
need to use undefined behavior somehow.
Post by Miguel Ojeda
Post by f***@gmail.com
Also, in order to not deduce the secret from other temporaries, any
value depending on a [[secret]] object is also marked implicitly as
[[secret]].
Post by f***@gmail.com
This does not address cache persistency, but it can be covered if the
[[secret]] can take an optional argument to ensure cache lines related to
this object are flushed (done by the compiler).
Post by f***@gmail.com
With this, you start to have a pretty strong security plan for stack
objects. But the heap objects cannot be marked as secret. So for that,
maybe you could mark the delete statement as [[secret]] and let the
compiler do the same thing for heap objects.
I would say users should not care where or how the value is stored.
Having to mark delete statements with an attribute seems odd.
The problem is, when you create an object on the heap, on don't really own
the object. that's why it needs a special treatment.
Maybe marking the pointer type as [[secret]] could solve the issue.
If you delete a [[secret]] pointer, then the compiler needs to ensure every
location is cleaned afterwards.
Post by Miguel Ojeda
As a
user, I would simply prefer to be able to mark my type T with
[[secret]] and then *that* could be put into the heap. That is the
reason I went for a template, because it looked natural to wrap values
std::secure_val<int> my_very_secret_number;
std::secure_val<char [N]> my_private_key;
etc.
The problem with your template approach is: you don't have the cascade of
the secret property, so temporaries depending on your secure_val will not
be cleaned.
Also, your template is not safely implementable in C++: you need
cooperation from the compiler in the same way as with the attribute,
because of the possible mutliple locations of your object.

Maybe we would need to have this in type system itself (very hard) with a
new qualifier.
Post by Miguel Ojeda
Post by f***@gmail.com
And also, a [[secret]] reference would need mark every dependant objects
as [[secret]], but the referenced object itself would not be cleaned.
Post by f***@gmail.com
Here I'm just throwing ideas into the wild, but I think you get the
idea.
Post by f***@gmail.com
All in all, I think it is possible to improve security with such
attributes, but I don't think an attribute on statements is the right way.
Indeed, I think a better idea is to work on the storage side, not on
the statement level.
Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/199794e8-8362-489b-818f-ab6c510c5c84%40isocpp.org.
Miguel Ojeda
2018-10-09 13:54:22 UTC
Permalink
Post by Miguel Ojeda
Hi Florian,
For your second point, I didn't think about it yet. So I didn't take it into consideration when I proposed the [[undead]] attribute. But if your goal is security, then you would also need to take into consideration this.
Let's imagine an attribute [[secret]].
Every object marked as [[secret]] will be cleaned before function exit.
This cleaning means set to zero every location that still contains the object (known to the compiler).
This sounds very similar to secure_val, but as a variable attribute.
Yes it is similar. But I think attribute is more appropriate because those security issues are not about C++: in order to read a destroyed value, you need to use undefined behavior somehow.
I am not sure what you mean by "are not about C++" or by "reading a
destroyed value". Do you mean you want to have compiler support so
that other languages (like C) can take advantage of it?

Note that there are C++-only attributes; and that, anyway, it would be
nice to have a concrete use case (e.g. secure_val) where such features
could be used.
Post by Miguel Ojeda
Also, in order to not deduce the secret from other temporaries, any value depending on a [[secret]] object is also marked implicitly as [[secret]].
This does not address cache persistency, but it can be covered if the [[secret]] can take an optional argument to ensure cache lines related to this object are flushed (done by the compiler).
With this, you start to have a pretty strong security plan for stack objects. But the heap objects cannot be marked as secret. So for that, maybe you could mark the delete statement as [[secret]] and let the compiler do the same thing for heap objects.
I would say users should not care where or how the value is stored.
Having to mark delete statements with an attribute seems odd.
The problem is, when you create an object on the heap, on don't really own the object. that's why it needs a special treatment.
Maybe marking the pointer type as [[secret]] could solve the issue.
Yes, exactly, that is why secure_val is a template: in my view, it has
to be applied the type; not on statements (Daniel's original proposal)
or variables (your initial [[secret]] proposal). If you create a type
attribute, then it could be used itself to implement (part of)
secure_val.
If you delete a [[secret]] pointer, then the compiler needs to ensure every location is cleaned afterwards.
Post by Miguel Ojeda
As a
user, I would simply prefer to be able to mark my type T with
[[secret]] and then *that* could be put into the heap. That is the
reason I went for a template, because it looked natural to wrap values
std::secure_val<int> my_very_secret_number;
std::secure_val<char [N]> my_private_key;
etc.
The problem with your template approach is: you don't have the cascade of the secret property, so temporaries depending on your secure_val will not be cleaned.
It depends. Note that the accesses to the secret value must go through
access(). This is intended so that code inside that block may be
treated specially by the compiler. The examples given in the proposal
about how this can be used are encryption (compiler support not needed
in principle), disabling speculation (compiler support needed), etc.
Also, your template is not safely implementable in C++: you need cooperation from the compiler in the same way as with the attribute, because of the possible mutliple locations of your object.
Of course it isn't, that is the whole point of secure_val. :-)

Let me put it this way: I would love secure_val to be implementable in
C++ (or at least part of it, e.g. the auto-clear [[secret]] part that
you are discussing). However, it is not clear yet how many things we
would need to add to the language or how. Some things, like
Spectre-class vulnerabilities, are still being researched. Therefore,
I suggested secure_val first to make the most common use case
concrete, and at the same time give developers a simple solution to
it. Since secure_val does not force almost anything on the vendors
(except the auto-clear), it can be updated to provide further
guarantees as time goes on.

Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANiq72mHdtv1H87QQWjRQzAa_BkCgr4SU9C2iOr7aJxGJJqf%2Bw%40mail.gmail.com.
f***@gmail.com
2018-10-09 14:12:37 UTC
Permalink
Post by f***@gmail.com
Post by Miguel Ojeda
Hi Florian,
Post by f***@gmail.com
For your second point, I didn't think about it yet. So I didn't take
it into consideration when I proposed the [[undead]] attribute. But if your
goal is security, then you would also need to take into consideration this.
Post by f***@gmail.com
Post by Miguel Ojeda
Post by f***@gmail.com
Let's imagine an attribute [[secret]].
Every object marked as [[secret]] will be cleaned before function
exit.
Post by f***@gmail.com
Post by Miguel Ojeda
Post by f***@gmail.com
This cleaning means set to zero every location that still contains
the object (known to the compiler).
Post by f***@gmail.com
Post by Miguel Ojeda
This sounds very similar to secure_val, but as a variable attribute.
Yes it is similar. But I think attribute is more appropriate because
those security issues are not about C++: in order to read a destroyed
value, you need to use undefined behavior somehow.
I am not sure what you mean by "are not about C++" or by "reading a
destroyed value". Do you mean you want to have compiler support so
that other languages (like C) can take advantage of it?
No, I mean these security issues arise beyond the scope of C++.
As far as C++ is concerned, you cannot access a destroyed value (so the
secret remains secret).
Any attempt in doing that leads to undefined behaviours: meaning the result
does not depends on C++ semantic anymore.
So if every single undefined behavior would crash the program instant
(which is actually valid), there would be no secret leaking issue at all.

That's what I mean when I say it is not about C++.

I don't necessarily want to have it for other languages (but it would be
good if we do).
Note that there are C++-only attributes; and that, anyway, it would be
nice to have a concrete use case (e.g. secure_val) where such features
could be used.
Post by f***@gmail.com
Post by Miguel Ojeda
Post by f***@gmail.com
Also, in order to not deduce the secret from other temporaries, any
value depending on a [[secret]] object is also marked implicitly as
[[secret]].
Post by f***@gmail.com
Post by Miguel Ojeda
Post by f***@gmail.com
This does not address cache persistency, but it can be covered if the
[[secret]] can take an optional argument to ensure cache lines related to
this object are flushed (done by the compiler).
Post by f***@gmail.com
Post by Miguel Ojeda
Post by f***@gmail.com
With this, you start to have a pretty strong security plan for stack
objects. But the heap objects cannot be marked as secret. So for that,
maybe you could mark the delete statement as [[secret]] and let the
compiler do the same thing for heap objects.
Post by f***@gmail.com
Post by Miguel Ojeda
I would say users should not care where or how the value is stored.
Having to mark delete statements with an attribute seems odd.
The problem is, when you create an object on the heap, on don't really
own the object. that's why it needs a special treatment.
Post by f***@gmail.com
Maybe marking the pointer type as [[secret]] could solve the issue.
Yes, exactly, that is why secure_val is a template: in my view, it has
to be applied the type; not on statements (Daniel's original proposal)
or variables (your initial [[secret]] proposal). If you create a type
attribute, then it could be used itself to implement (part of)
secure_val.
true.
Post by f***@gmail.com
If you delete a [[secret]] pointer, then the compiler needs to ensure
every location is cleaned afterwards.
Post by f***@gmail.com
Post by Miguel Ojeda
As a
user, I would simply prefer to be able to mark my type T with
[[secret]] and then *that* could be put into the heap. That is the
reason I went for a template, because it looked natural to wrap values
std::secure_val<int> my_very_secret_number;
std::secure_val<char [N]> my_private_key;
etc.
The problem with your template approach is: you don't have the cascade
of the secret property, so temporaries depending on your secure_val will
not be cleaned.
It depends. Note that the accesses to the secret value must go through
access(). This is intended so that code inside that block may be
treated specially by the compiler. The examples given in the proposal
about how this can be used are encryption (compiler support not needed
in principle), disabling speculation (compiler support needed), etc.
Your encryption use case actually needs compiler support if your compiler
is "smart" enough to duplicate your object location.
Post by f***@gmail.com
Also, your template is not safely implementable in C++: you need
cooperation from the compiler in the same way as with the attribute,
because of the possible mutliple locations of your object.
Of course it isn't, that is the whole point of secure_val. :-)
Let me put it this way: I would love secure_val to be implementable in
C++ (or at least part of it, e.g. the auto-clear [[secret]] part that
you are discussing). However, it is not clear yet how many things we
would need to add to the language or how. Some things, like
Spectre-class vulnerabilities, are still being researched. Therefore,
I suggested secure_val first to make the most common use case
concrete, and at the same time give developers a simple solution to
it. Since secure_val does not force almost anything on the vendors
(except the auto-clear), it can be updated to provide further
guarantees as time goes on.
The auto-clear does require compiler support if you want a proper/safe
implementation of it.
But you're right: it can be done incrementally.

Cheers,
Florian
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/171c3741-7ebf-4383-83eb-ed68b08b10b2%40isocpp.org.
Miguel Ojeda
2018-10-09 14:31:46 UTC
Permalink
Post by f***@gmail.com
Post by Miguel Ojeda
I am not sure what you mean by "are not about C++" or by "reading a
destroyed value". Do you mean you want to have compiler support so
that other languages (like C) can take advantage of it?
No, I mean these security issues arise beyond the scope of C++.
Agreed, but I am not following what you mean by that (see below).
Post by f***@gmail.com
As far as C++ is concerned, you cannot access a destroyed value (so the secret remains secret).
Any attempt in doing that leads to undefined behaviours: meaning the result does not depends on C++ semantic anymore.
So if every single undefined behavior would crash the program instant (which is actually valid), there would be no secret leaking issue at all.
This is not only about code in the same process reading an old value
(the undefined behavior that I suspect you are talking about). You
also have other things, like core dumps, external agents... Of course,
all outside the scope of C++ in that sense.

In any case, regardless of that, I am not sure why you said "I think
attribute is more appropriate because those security issues are not
about C++". How is that related to this being implemented as an
attribute or not?
Post by f***@gmail.com
That's what I mean when I say it is not about C++.
Agreed.
Post by f***@gmail.com
I don't necessarily want to have it for other languages (but it would be good if we do).
Ditto.
Post by f***@gmail.com
Post by Miguel Ojeda
It depends. Note that the accesses to the secret value must go through
access(). This is intended so that code inside that block may be
treated specially by the compiler. The examples given in the proposal
about how this can be used are encryption (compiler support not needed
in principle), disabling speculation (compiler support needed), etc.
Your encryption use case actually needs compiler support if your compiler is "smart" enough to duplicate your object location.
That is why I said "in principle" :-)
Post by f***@gmail.com
Post by Miguel Ojeda
Also, your template is not safely implementable in C++: you need cooperation from the compiler in the same way as with the attribute, because of the possible mutliple locations of your object.
Of course it isn't, that is the whole point of secure_val. :-)
Let me put it this way: I would love secure_val to be implementable in
C++ (or at least part of it, e.g. the auto-clear [[secret]] part that
you are discussing). However, it is not clear yet how many things we
would need to add to the language or how. Some things, like
Spectre-class vulnerabilities, are still being researched. Therefore,
I suggested secure_val first to make the most common use case
concrete, and at the same time give developers a simple solution to
it. Since secure_val does not force almost anything on the vendors
(except the auto-clear), it can be updated to provide further
guarantees as time goes on.
The auto-clear does require compiler support if you want a proper/safe implementation of it.
I am confused: that is what I said, no?

By the way, to avoid confusion: the [[secret]] portion of the
auto-clear requires compiler support. The simple part of zero'ing
memory on destruction (in the sense of calling a secure clear function
that is not optimized away) can be done --- even if as a
workaround/hack --- without compiler support (as some projects/OSs
implement already).

Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANiq72m6M2YY50UGGKnr4GD7VXtS7isG1nQHh9MhKHFbG97bJw%40mail.gmail.com.
Daniel Gutson
2018-10-09 12:57:38 UTC
Permalink
(Top posting intentional)

I will wrote a detailed case ofnthe issue once I research the security
issue (and try to write an exploit as a PoC) before any language proposal.

At language proposal I will start over a new thread because it should cover
value tainting and containers (both user defined and standard).
For example
std::vector<std::string>
with or without specially fitted destructors.
I will not engange in any further discussion until I understand the broader
situation I referred to.
I think that this should involve type strongness since a function my pass a
sensitive function to a callee, and the "sensitiveness" of data should be
propagated for any operations the callee may do.
I already experienced this before when using C's FILE* where the io library
caches data internally forcing me to call setbuff(nullptr) (didn't
experiment with the C++'s streaming library yet).

Again, thanks for all the useful feedback. I don't want to spam more people
and want to "stop and think" quietly :)

It even leads to a security conference paper.
Post by Miguel Ojeda
Hi Florian,
Post by f***@gmail.com
For your second point, I didn't think about it yet. So I didn't take it
into consideration when I proposed the [[undead]] attribute. But if your
goal is security, then you would also need to take into consideration this.
Post by f***@gmail.com
Let's imagine an attribute [[secret]].
Every object marked as [[secret]] will be cleaned before function exit.
This cleaning means set to zero every location that still contains the
object (known to the compiler).
This sounds very similar to secure_val, but as a variable attribute.
Post by f***@gmail.com
Also, in order to not deduce the secret from other temporaries, any
value depending on a [[secret]] object is also marked implicitly as
[[secret]].
Post by f***@gmail.com
This does not address cache persistency, but it can be covered if the
[[secret]] can take an optional argument to ensure cache lines related to
this object are flushed (done by the compiler).
Post by f***@gmail.com
With this, you start to have a pretty strong security plan for stack
objects. But the heap objects cannot be marked as secret. So for that,
maybe you could mark the delete statement as [[secret]] and let the
compiler do the same thing for heap objects.
I would say users should not care where or how the value is stored.
Having to mark delete statements with an attribute seems odd. As a
user, I would simply prefer to be able to mark my type T with
[[secret]] and then *that* could be put into the heap. That is the
reason I went for a template, because it looked natural to wrap values
std::secure_val<int> my_very_secret_number;
std::secure_val<char [N]> my_private_key;
etc.
Post by f***@gmail.com
And also, a [[secret]] reference would need mark every dependant objects
as [[secret]], but the referenced object itself would not be cleaned.
Post by f***@gmail.com
Here I'm just throwing ideas into the wild, but I think you get the idea.
All in all, I think it is possible to improve security with such
attributes, but I don't think an attribute on statements is the right way.
Indeed, I think a better idea is to work on the storage side, not on
the statement level.
Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANiq72kBPp9uONTPvC7L9n8%2BrtnXtE12MM_YJQDw1JsbVQ9frA%40mail.gmail.com
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-2oUcYW6CrwESORd4JF8qvKNxABtweWb_nSei5xoMdK%3DA%40mail.gmail.com.
Magnus Fromreide
2018-10-09 06:21:57 UTC
Permalink
Post by Andrew Giese
What about using [[nodiscard]] as a null-statement?
Similar to how [[fallthrough]] is a null statement intended to indicate to
the compiler and reader that the fallthrough is intentional, a
[[nodiscard]] after an assignment or a memset should indicate that the
previous statement was intentional and should not be discarded.
e.g.
memset(password, 0, PASSWORD_SIZE);
[[nodiscard]]; // intentionally store before a free
free(password);
I think the use of an attribute for this purpose is problematic.

The first reason is the good old attributes may be ignored argument - this
means that if a compiler ain't supporting this attribute then the resulting
code is broken, no diagnostic allowed.

The second reason is that what is cared about here is the values. If the
compiler is told that the value is used after the memset then it won't
remove it so I think something like

void use(T) { }

and

void use(T*, size_t) { }


but somehow marked to tell the compiler that the argument passed is
used so you better don't optimize it away is more useful.

memset(password, 0, PASSWORD_SIZE);
use(password, PASSWOD_SIZE);
free(password);

/MF
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are proposing
is compatible with the current language.
I just wanted to highlight that it might be misleading to have the same
attribute with different meaning when it is used on a function declaration,
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force the
last assignment, but to force the last value of the variable, wherever the
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute whose
meaning would be that the object might be accessed after its lifetime end
and so the last assignment should be kept and propagated to every storage
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it
becomes valid to access it afterwards.
It would tell the compiler it should behave as-if the object *could*
be accessed afterwards.
Actually I would like to tell the compiler that the object should NOT be
accessible afterwards.
What I said is not "the compiler makes the object accessible", but
"whatever the compiler will do, the object will remain accessible somehow,
and so the correctness of the whole program depends on the last value not
being discarded".
Your view is also correct, but a bit more magic: when this "destroy all
the places where the object is" is performed? (the right answer is: just
after its destructor is called)
While in what I propose, it is done more explicitly when the last value
is assigned.
But both are good. It's just a matter of taste at this point.
However, your first proposal doesn't work that well: ok you tell the
compiler to keep the assignment. But which location is used for this
assignment? All of them? The last one? The main one? A new one?
And if you start standardizing which location should be assigned, then
you're not talking about expressions anymore, but about objects. So
attributes on expressions is not the right tool for you.
Post by Daniel Gutson
Additionally I would like to reuse the existing attribute name, though
this is of least importance now.
Here, I completely disagree.
Ok let's not discuss this.
It should not be an already existing attribute name unless the feature is
Post by f***@gmail.com
close enough to the original attribute.
And the new meaning you proposed is (at least for me) too far from the
original, and is misleading.
An attribute is not a keyword, it is easy to create new ones (easier than
repurposing an old one?).
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c35b213e-cbfd-41e2-a8dd-e5cf93343b8c%40isocpp.org.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/20181009062157.GA4566%40noemi.bahnhof.se.
Daniel Gutson
2018-10-09 10:29:52 UTC
Permalink
Post by Magnus Fromreide
Post by Andrew Giese
What about using [[nodiscard]] as a null-statement?
Similar to how [[fallthrough]] is a null statement intended to indicate
to
Post by Andrew Giese
the compiler and reader that the fallthrough is intentional, a
[[nodiscard]] after an assignment or a memset should indicate that the
previous statement was intentional and should not be discarded.
e.g.
memset(password, 0, PASSWORD_SIZE);
[[nodiscard]]; // intentionally store before a free
free(password);
I think the use of an attribute for this purpose is problematic.
The first reason is the good old attributes may be ignored argument - this
means that if a compiler ain't supporting this attribute then the resulting
code is broken, no diagnostic allowed.
What would exactly broken mean here?
Post by Magnus Fromreide
The second reason is that what is cared about here is the values. If the
compiler is told that the value is used after the memset then it won't
remove it so I think something like
void use(T) { }
and
void use(T*, size_t) { }
but somehow marked to tell the compiler that the argument passed is
used so you better don't optimize it away is more useful.
memset(password, 0, PASSWORD_SIZE);
use(password, PASSWOD_SIZE);
This may allow
use(password, PASSWORD_SIZE-1)
or
use(password+1, ...)
for example.
We don't want to mess the value tracker that way.
I stick to the attribute version.
See my related answer below to Miguel Ojeda.


free(password);
Post by Magnus Fromreide
/MF
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are
proposing
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
is compatible with the current language.
I just wanted to highlight that it might be misleading to have the
same
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
attribute with different meaning when it is used on a function
declaration,
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force
the
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
last assignment, but to force the last value of the variable,
wherever the
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute
whose
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
meaning would be that the object might be accessed after its
lifetime end
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
and so the last assignment should be kept and propagated to every
storage
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it
becomes valid to access it afterwards.
It would tell the compiler it should behave as-if the object
*could*
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
be accessed afterwards.
Actually I would like to tell the compiler that the object should
NOT be
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
accessible afterwards.
What I said is not "the compiler makes the object accessible", but
"whatever the compiler will do, the object will remain accessible
somehow,
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
and so the correctness of the whole program depends on the last value
not
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
being discarded".
Your view is also correct, but a bit more magic: when this "destroy
all
just
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
after its destructor is called)
While in what I propose, it is done more explicitly when the last
value
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
is assigned.
But both are good. It's just a matter of taste at this point.
However, your first proposal doesn't work that well: ok you tell the
compiler to keep the assignment. But which location is used for this
assignment? All of them? The last one? The main one? A new one?
And if you start standardizing which location should be assigned,
then
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
you're not talking about expressions anymore, but about objects. So
attributes on expressions is not the right tool for you.
Post by Daniel Gutson
Additionally I would like to reuse the existing attribute name,
though
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
this is of least importance now.
Here, I completely disagree.
Ok let's not discuss this.
It should not be an already existing attribute name unless the feature
is
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
close enough to the original attribute.
And the new meaning you proposed is (at least for me) too far from
the
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
original, and is misleading.
An attribute is not a keyword, it is easy to create new ones (easier
than
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
repurposing an old one?).
--
You received this message because you are subscribed to the Google
Groups
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it,
send an
<javascript:>.
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
<
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org?utm_medium=email&utm_source=footer
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
Post by Andrew Giese
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c35b213e-cbfd-41e2-a8dd-e5cf93343b8c%40isocpp.org
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/20181009062157.GA4566%40noemi.bahnhof.se
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-0wY9Qs8hS%2B2UpeqKY-NkZ2edcrfcLW4Jt8UpahXxOLZg%40mail.gmail.com.
Magnus Fromreide
2018-10-09 22:13:55 UTC
Permalink
Post by Daniel Gutson
Post by Magnus Fromreide
Post by Andrew Giese
What about using [[nodiscard]] as a null-statement?
Similar to how [[fallthrough]] is a null statement intended to indicate
to
Post by Andrew Giese
the compiler and reader that the fallthrough is intentional, a
[[nodiscard]] after an assignment or a memset should indicate that the
previous statement was intentional and should not be discarded.
e.g.
memset(password, 0, PASSWORD_SIZE);
[[nodiscard]]; // intentionally store before a free
free(password);
I think the use of an attribute for this purpose is problematic.
The first reason is the good old attributes may be ignored argument - this
means that if a compiler ain't supporting this attribute then the resulting
code is broken, no diagnostic allowed.
What would exactly broken mean here?
It would mean that you can't detect if your compiler supports the feature you
are asking for in any way and that might be surprising for users that expect
the clearing of the values to happen but instead they end upp with their
secrets still in memory, i.e. the same situation as today but worse.
Post by Daniel Gutson
Post by Magnus Fromreide
The second reason is that what is cared about here is the values. If the
compiler is told that the value is used after the memset then it won't
remove it so I think something like
void use(T) { }
and
void use(T*, size_t) { }
but somehow marked to tell the compiler that the argument passed is
used so you better don't optimize it away is more useful.
memset(password, 0, PASSWORD_SIZE);
use(password, PASSWOD_SIZE);
This may allow
use(password, PASSWORD_SIZE-1)
or
use(password+1, ...)
for example.
True, but I expect this usage to be rare and you can write ugly code in all
languages (see below).
Post by Daniel Gutson
We don't want to mess the value tracker that way.
I also think it is good to be explicit about what walue it is you are talking
about, consider

memset(foo1, 0, sizeof(foo1)), memset(&foo2, 0, sizeof(foo2));
[[nodiscard]];

Does nodiscard apply to foo1, *foo1, foo2 or some combination of them?

/MF
Post by Daniel Gutson
I stick to the attribute version.
See my related answer below to Miguel Ojeda.
free(password);
Post by Magnus Fromreide
/MF
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
I completely understood what you meant, and yes what you are
proposing
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
is compatible with the current language.
I just wanted to highlight that it might be misleading to have the
same
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
attribute with different meaning when it is used on a function
declaration,
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
or on an expression (a declaration is also a statement).
Also, after some thinking, in this case, the goal is not to force
the
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
last assignment, but to force the last value of the variable,
wherever the
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
variable is, even if the variable is both in register and stack.
So in that case, you might be better with a [[undead]] attribute
whose
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
meaning would be that the object might be accessed after its
lifetime end
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
and so the last assignment should be kept and propagated to every
storage
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
void f() {
[[undead]] int secret;
/* ... */
secret = 0;
}
That wouldn't mean the lifetime of the object is extended and it
becomes valid to access it afterwards.
It would tell the compiler it should behave as-if the object
*could*
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
Post by f***@gmail.com
be accessed afterwards.
Actually I would like to tell the compiler that the object should
NOT be
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
accessible afterwards.
What I said is not "the compiler makes the object accessible", but
"whatever the compiler will do, the object will remain accessible
somehow,
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
and so the correctness of the whole program depends on the last value
not
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
being discarded".
Your view is also correct, but a bit more magic: when this "destroy
all
just
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
after its destructor is called)
While in what I propose, it is done more explicitly when the last
value
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
is assigned.
But both are good. It's just a matter of taste at this point.
However, your first proposal doesn't work that well: ok you tell the
compiler to keep the assignment. But which location is used for this
assignment? All of them? The last one? The main one? A new one?
And if you start standardizing which location should be assigned,
then
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
you're not talking about expressions anymore, but about objects. So
attributes on expressions is not the right tool for you.
Post by Daniel Gutson
Additionally I would like to reuse the existing attribute name,
though
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
Post by Daniel Gutson
this is of least importance now.
Here, I completely disagree.
Ok let's not discuss this.
It should not be an already existing attribute name unless the feature
is
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
close enough to the original attribute.
And the new meaning you proposed is (at least for me) too far from
the
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
original, and is misleading.
An attribute is not a keyword, it is easy to create new ones (easier
than
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
repurposing an old one?).
--
You received this message because you are subscribed to the Google
Groups
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it,
send an
<javascript:>.
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
<
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dba0bf6d-92da-440e-8e61-af336cacd537%40isocpp.org?utm_medium=email&utm_source=footer
Post by Andrew Giese
Post by Daniel Gutson
Post by f***@gmail.com
.
--
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Future Proposals" group.
Post by Andrew Giese
To unsubscribe from this group and stop receiving emails from it, send
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c35b213e-cbfd-41e2-a8dd-e5cf93343b8c%40isocpp.org
.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/20181009062157.GA4566%40noemi.bahnhof.se
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-0wY9Qs8hS%2B2UpeqKY-NkZ2edcrfcLW4Jt8UpahXxOLZg%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/20181009221354.GA8206%40noemi.bahnhof.se.
Arthur O'Dwyer
2018-10-10 05:55:16 UTC
Permalink
Post by Andrew Giese
Post by Daniel Gutson
Post by Magnus Fromreide
Post by Andrew Giese
What about using [[nodiscard]] as a null-statement?
Similar to how [[fallthrough]] is a null statement intended to
indicate to
Post by Daniel Gutson
Post by Magnus Fromreide
Post by Andrew Giese
the compiler and reader that the fallthrough is intentional, a
[[nodiscard]] after an assignment or a memset should indicate that
the
Post by Daniel Gutson
Post by Magnus Fromreide
Post by Andrew Giese
previous statement was intentional and should not be discarded.
e.g.
memset(password, 0, PASSWORD_SIZE);
[[nodiscard]]; // intentionally store before a free
free(password);
I think the use of an attribute for this purpose is problematic.
The first reason is the good old attributes may be ignored argument -
this
Post by Daniel Gutson
Post by Magnus Fromreide
means that if a compiler ain't supporting this attribute then the
resulting
Post by Daniel Gutson
Post by Magnus Fromreide
code is broken, no diagnostic allowed.
What would exactly broken mean here?
It would mean that you can't detect if your compiler supports the feature you
are asking for in any way and that might be surprising for users that expect
the clearing of the values to happen but instead they end up with their
secrets still in memory, i.e. the same situation as today but worse.
FWIW, I must disagree narrowly with this reasoning. I myself do tend to
think this way, but I think the Committee (rightly) tends to take the long
view — if it's a feature we really need, then it's better to suffer a few
years of incomplete support in order to improve the lives of programmers
five or ten years down the road.
I concur with your opinion, though, that this "nodiscard statement" is *not*
something that we really need, at least not in this ill-specified and
ill-motivated form.
Post by Andrew Giese
Post by Daniel Gutson
Post by Magnus Fromreide
memset(password, 0, PASSWORD_SIZE);
use(password, PASSWOD_SIZE);
This may allow
use(password, PASSWORD_SIZE-1)
or
use(password+1, ...)
for example.
We don't want to mess the value tracker that way.
I also think it is good to be explicit about what walue it is you are talking
about, consider
memset(foo1, 0, sizeof(foo1)), memset(&foo2, 0, sizeof(foo2));
[[nodiscard]];
Does nodiscard apply to foo1, *foo1, foo2 or some combination of them?
This "nodiscard statement" idea is actually already implemented in
compilers today, with a much more sensible syntax. It's used in Google
Benchmark, for example. They spell it benchmark::ClobberMemory(), and the
implementation is in terms of a no-op "volatile __asm__" statement.
Programmers who need this sort of thing today should definitely be aware of
ClobberMemory().

https://github.com/google/benchmark#preventing-optimisation

This will avoid removing memset's "writes" to "memory"; but of course that
doesn't matter to the security angle, unless you're working on hardware
where you personally know what "write" and "memory" actually mean. (I doubt
many participants in this discussion are working on such platforms; and if
they are, they aren't concerned about security in this sense.)

–Arthur
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/47e783a1-ed11-4c62-be5f-065873b8e4aa%40isocpp.org.
Arthur O'Dwyer
2018-09-28 22:22:25 UTC
Permalink
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
So meaning would be different.
In that respect, another attribute name might be better.
Right. The standard attribute [[nodiscard]] goes in a *library* and
instructs the compiler to kick* the user* if the user has *forgotten to use* the
result of some *library call*.

Daniel, what you are asking for is an attribute that goes in *user code*
and instructs the compiler to kick *itself?* if the user has *forgotten to
use* the result of some *assignment expression*.


Also, it is already possible (but cumbersome) to implement already without
Post by f***@gmail.com
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
This certainly seems to make sure that the write reaches L1 cache, but do
you know whether the write is guaranteed to have reached and overwritten
any copies of the data that might remain in L2 and main memory?
What about the swap partition? Are you worried that a copy of the secret
may have been swapped out to disk? (Reductio ad absurdum: What if it was
swapped out to removable media that has since been ejected?)

Before you can start talking meaningfully about preventing the compiler
from eliminating your dead "=0" statements, you need to have a mental model
that explains what good those "=0" statements are supposed to do in the
first place.

HTH,
Arthur
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1442c15c-6a58-4f3e-83cf-9f5554fb9981%40isocpp.org.
f***@gmail.com
2018-09-28 22:33:55 UTC
Permalink
Post by Arthur O'Dwyer
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
So meaning would be different.
In that respect, another attribute name might be better.
Right. The standard attribute [[nodiscard]] goes in a *library* and
instructs the compiler to kick* the user* if the user has *forgotten to
use* the result of some *library call*.
Daniel, what you are asking for is an attribute that goes in *user code*
and instructs the compiler to kick *itself?* if the user has *forgotten
to use* the result of some *assignment expression*.
Also, it is already possible (but cumbersome) to implement already without
Post by f***@gmail.com
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
This certainly seems to make sure that the write reaches L1 cache, but do
you know whether the write is guaranteed to have reached and overwritten
any copies of the data that might remain in L2 and main memory?
What about the swap partition? Are you worried that a copy of the secret
may have been swapped out to disk? (Reductio ad absurdum: What if it was
swapped out to removable media that has since been ejected?)
Before you can start talking meaningfully about preventing the compiler
from eliminating your dead "=0" statements, you need to have a mental model
that explains what good those "=0" statements are supposed to do in the
first place.
That's why I introduced the [[undead]] attribute: to let the compiler do
what is necessary to propagate the value where it is meaningful, and
flushing the according cacheline might be part of this process (I assume
user code can flush a specific cache line).
Because you don't care about the assignment per se, but you care about the
value that is visible afterwards.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/866660c0-4c90-4ce9-bd5c-16ff593d35d6%40isocpp.org.
Ray Hamel
2018-10-02 03:17:17 UTC
Permalink
Arthur,

Sure, it wouldn't provide *perfect* security, but ensuring the secret is
overwritten, whether that's in L1 cache or elsewhere, ensures that at
minimum it's can't be recovered without some special exploit, side-channel
or physical access to the hardware. And if Eve has some exploit that lets
her read from arbitrary DRAM or storage on Alice's computer, then Alice is
pretty much screwed anyway; there's very little you can do to harden
software against an attacker who has so thoroughly compromised the host
system.

-Ray
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8aa1ec5f-ebde-43de-b3c4-a30a434c552d%40isocpp.org.
Daniel Gutson
2018-10-07 04:57:23 UTC
Permalink
Post by Ray Hamel
Arthur,
Sure, it wouldn't provide *perfect* security, but ensuring the secret is
overwritten, whether that's in L1 cache or elsewhere, ensures that at
minimum it's can't be recovered without some special exploit, side-channel
or physical access to the hardware. And if Eve has some exploit that lets
her read from arbitrary DRAM or storage on Alice's computer, then Alice is
pretty much screwed anyway; there's very little you can do to harden
software against an attacker who has so thoroughly compromised the host
system.
I thought of memory (stack, heap, red zone), and registers. I didn't think
of cache. This would open yet another exploit surface. Though very hard to
exploit.
I still think that the attribute solution is a very good start and
addresses a lot of existing problems.
Post by Ray Hamel
-Ray
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8aa1ec5f-ebde-43de-b3c4-a30a434c552d%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8aa1ec5f-ebde-43de-b3c4-a30a434c552d%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-1%2BKdnbjB8F3Hsa9KS5R1KdvMqPnARKPeM963PggDwNCQ%40mail.gmail.com.
Daniel Gutson
2018-10-07 04:50:15 UTC
Permalink
El vie., 28 de sep. de 2018 a la(s) 19:22, Arthur O'Dwyer (
Post by Arthur O'Dwyer
Post by f***@gmail.com
I want to highlight that [[nodiscard]] on functions is not about forcing
the compiler to keep the value, but instead to emit a warning if the user
doesn't use the value.
So meaning would be different.
In that respect, another attribute name might be better.
Right. The standard attribute [[nodiscard]] goes in a *library* and
instructs the compiler to kick* the user* if the user has *forgotten to
use* the result of some *library call*.
Daniel, what you are asking for is an attribute that goes in *user code*
and instructs the compiler to kick *itself?* if the user has *forgotten
to use* the result of some *assignment expression*.
Let's see. First, I don't see a need to distinguish between user code and
library code in this context (whereas it makes sense for [[nodiscard]] on
functions). What I am asking for goes anywhere, either user or library code.
Second, the attribute targets the compiler: is a tool that the programmer
can use to tell the compiler "this statement should not be discarded". What
the compiler does with that information is implementation defined: it can
just ignore it, it can honor it and not discard the statement, or it can
warn the user that it will discard it anyways (a warning), so the user can
later decide what to do (for example, recode the snippet, use volatile,
etc.).
Post by Arthur O'Dwyer
Also, it is already possible (but cumbersome) to implement already without
Post by f***@gmail.com
void f() {
int secret_int;
float secret_float;
/* ... */
secret_int = 0;
secret_float = 0
asm volatile ("" ::"irm"(secret_int), "xm"(secret_float));
}
This certainly seems to make sure that the write reaches L1 cache, but do
you know whether the write is guaranteed to have reached and overwritten
any copies of the data that might remain in L2 and main memory?
What about the swap partition? Are you worried that a copy of the secret
may have been swapped out to disk? (Reductio ad absurdum: What if it was
swapped out to removable media that has since been ejected?)
Before you can start talking meaningfully about preventing the compiler
from eliminating your dead "=0" statements, you need to have a mental model
that explains what good those "=0" statements are supposed to do in the
first place.
HTH,
Arthur
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1442c15c-6a58-4f3e-83cf-9f5554fb9981%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1442c15c-6a58-4f3e-83cf-9f5554fb9981%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-2WAF_RZR_fTAXdhP842WaBJ-m27nbTaCXDK3me1Y61tw%40mail.gmail.com.
Thiago Macieira
2018-10-07 07:30:07 UTC
Permalink
Post by Arthur O'Dwyer
This certainly seems to make sure that the write reaches L1 cache, but do
you know whether the write is guaranteed to have reached and overwritten
any copies of the data that might remain in L2 and main memory?
What about the swap partition? Are you worried that a copy of the secret
may have been swapped out to disk? (Reductio ad absurdum: What if it was
swapped out to removable media that has since been ejected?)
Before you can start talking meaningfully about preventing the compiler
from eliminating your dead "=0" statements, you need to have a mental model
that explains what good those "=0" statements are supposed to do in the
first place.
I agree, this needs some further thinking to define the problem. Just tackling
the problem of eliminated stores is insufficient, since the same data could be
found elsewhere, like in registers. That's why the -mzero-caller-saved-regs
patch exists for GCC
https://github.com/clearlinux-pkgs/gcc/blob/master/zero-regs-gcc8.patch

A function attribute is the best way to solve the problem of local variables:
just tell the compiler to clear ALL variables, both in stack and in registers.
Or maybe provide hints to the compiler of which variables are hazardous and
must be cleared, so it won't spend CPU cycles clearing a large but innocuous
buffer.

Similarly for memory-allocated blocks, as the compilers do understand free()
and that any stores prior to that are dead. But I also don't think this is
that big a security issue, as secure code must have used mlock() to prevent
swapping out, so it will have to use munlock() after it cleared the memory,
meaning the compiler cannot conclude it's a dead store.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2144977.3D1Rvy5359%40tjmaciei-mobl1.
Daniel Gutson
2018-10-07 14:46:41 UTC
Permalink
Post by Thiago Macieira
Post by Arthur O'Dwyer
This certainly seems to make sure that the write reaches L1 cache, but do
you know whether the write is guaranteed to have reached and overwritten
any copies of the data that might remain in L2 and main memory?
What about the swap partition? Are you worried that a copy of the secret
may have been swapped out to disk? (Reductio ad absurdum: What if it was
swapped out to removable media that has since been ejected?)
Before you can start talking meaningfully about preventing the compiler
from eliminating your dead "=0" statements, you need to have a mental
model
Post by Arthur O'Dwyer
that explains what good those "=0" statements are supposed to do in the
first place.
I agree, this needs some further thinking to define the problem. Just tackling
the problem of eliminated stores is insufficient, since the same data could be
found elsewhere, like in registers. That's why the
-mzero-caller-saved-regs
patch exists for GCC
https://github.com/clearlinux-pkgs/gcc/blob/master/zero-regs-gcc8.patch
just tell the compiler to clear ALL variables, both in stack and in registers.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69976

:)
Post by Thiago Macieira
Or maybe provide hints to the compiler of which variables are hazardous and
must be cleared, so it won't spend CPU cycles clearing a large but innocuous
buffer.
I think this is both incomplete and extracomplicated. You all are thinking
in stores only (yes, I started it ny mentioning DSE in the first place, I
admit it), but I want to make it statement-wise and let the implementation
decide what to do.
Function level attributes are useful for a separate matter (Return Oriented
Programming prevention, filed Intel IP here :( which I highly regret now)
but for DSEs is an overkill. For example a function may declare a local
buffer and an index to iterate it; the buffer may be sensible but the index
whould normally be placed in a register which is safe. Marking the function
as sensible may cause reloading and a large performance overhead. Not
useful.
I stick to the idea of marking statements being assignments, function
calls, whatever, letting the compiler decide what to do.
Post by Thiago Macieira
Similarly for memory-allocated blocks, as the compilers do understand free()
and that any stores prior to that are dead. But I also don't think this is
that big a security issue, as secure code must have used mlock() to prevent
swapping out, so it will have to use munlock() after it cleared the memory,
meaning the compiler cannot conclude it's a dead store.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2144977.3D1Rvy5359%40tjmaciei-mobl1
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-0DixoBS5y_0GwE2AydDa2AMx8ie-mL1PD_WAivunCENw%40mail.gmail.com.
Miguel Ojeda
2018-10-09 07:02:29 UTC
Permalink
Hi Daniel,
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
For this specific case (data that must be kept as secret as reasonably
possible, like passwords, secrets, keying data...), I am proposing
`secure_clear` (a memset_s-like function and function template) and
`secure_val` (a new class template) in P1315 for the next mailing.
Meanwhile that is out, please take a look at:

https://ojeda.io/cpp/secure_val

As long as your proposal allows to write functionality like
`secure_clear` and `secure_val` as portably and easily as possible, it
seems useful!

Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANiq72%3D4-NBXg28AVBbaY83jLgTNRowmKiMT8Sgk28jTUu2xfw%40mail.gmail.com.
Michał Gawron
2018-10-09 07:25:48 UTC
Permalink
Wouldn't something like this as a std:: function work?

template<class T>
inline add_volatile<T>&
make_volatile (T& t)
{
return t;
}

Then later:

int a = 5;


make_volatile (a) = 0;


std::best_regards();
Post by Miguel Ojeda
Hi Daniel,
For this specific case (data that must be kept as secret as reasonably
possible, like passwords, secrets, keying data...), I am proposing
`secure_clear` (a memset_s-like function and function template) and
`secure_val` (a new class template) in P1315 for the next mailing.
https://ojeda.io/cpp/secure_val
As long as your proposal allows to write functionality like
`secure_clear` and `secure_val` as portably and easily as possible, it
seems useful!
Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1aa6c911-439e-4469-806d-bdc39989ad40%40isocpp.org.
Richard Hodges
2018-10-09 10:29:44 UTC
Permalink
Post by Michał Gawron
Wouldn't something like this as a std:: function work?
template<class T>
inline add_volatile<T>&
make_volatile (T& t)
{
return t;
}
I had the same thought. The old assembler/c-hacker in me, which screams
"it's all just bl**dy memory!!" completely agrees with you (although
shouldn't it be `add_volatile_t<T>&` ?.

Would this require a language change?
Post by Michał Gawron
int a = 5;


make_volatile (a) = 0;
std::best_regards();
Post by Miguel Ojeda
Hi Daniel,
For this specific case (data that must be kept as secret as reasonably
possible, like passwords, secrets, keying data...), I am proposing
`secure_clear` (a memset_s-like function and function template) and
`secure_val` (a new class template) in P1315 for the next mailing.
https://ojeda.io/cpp/secure_val
As long as your proposal allows to write functionality like
`secure_clear` and `secure_val` as portably and easily as possible, it
seems useful!
Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1aa6c911-439e-4469-806d-bdc39989ad40%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1aa6c911-439e-4469-806d-bdc39989ad40%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALvx3hboWxMcpiQbiUbRCZK8jdskm_3Hn%3DHx5ATGf7MnLHhdgA%40mail.gmail.com.
Daniel Gutson
2018-10-09 10:36:52 UTC
Permalink
Post by Michał Gawron
Wouldn't something like this as a std:: function work?
template<class T>
inline add_volatile<T>&
make_volatile (T& t)
{
return t;
}
int a = 5;


make_volatile (a) = 0;
What about function calls? What about memory regions?
Post by Michał Gawron
std::best_regards();
Post by Miguel Ojeda
Hi Daniel,
For this specific case (data that must be kept as secret as reasonably
possible, like passwords, secrets, keying data...), I am proposing
`secure_clear` (a memset_s-like function and function template) and
`secure_val` (a new class template) in P1315 for the next mailing.
https://ojeda.io/cpp/secure_val
As long as your proposal allows to write functionality like
`secure_clear` and `secure_val` as portably and easily as possible, it
seems useful!
Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1aa6c911-439e-4469-806d-bdc39989ad40%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1aa6c911-439e-4469-806d-bdc39989ad40%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-0dqO7n9miYxbWYafWSV%2B_E2LO0%3DKmTd5%3D_4xem2bZJ2Q%40mail.gmail.com.
Daniel Gutson
2018-10-09 10:34:43 UTC
Permalink
Post by Miguel Ojeda
Hi Daniel,
Hola Miguel,
Post by Miguel Ojeda
Post by Daniel Gutson
Yeah. But please note that this is not only for function calls.
void f()
{
int secret;
....
secret = 0; //removed due to DSE
}
For this specific case (data that must be kept as secret as reasonably
possible, like passwords, secrets, keying data...), I am proposing
`secure_clear` (a memset_s-like function and function template) and
`secure_val` (a new class template) in P1315 for the next mailing.
https://ojeda.io/cpp/secure_val
As long as your proposal allows to write functionality like
`secure_clear` and `secure_val` as portably and easily as possible, it
seems useful!
I just read the proposal and I'm glad I'm not alone :)
Please keep in mind that there are other cases. For example, doing stuff
over IO mapped memory.
This particularly may be a bug and a different thread, but a call to
std::fill_n over a volatile-qualified buffer gets removed in the gcc,
clang, icc and MSVC.
OTOH does your secure_val allow the value placed in registers?
Post by Miguel Ojeda
Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANiq72%3D4-NBXg28AVBbaY83jLgTNRowmKiMT8Sgk28jTUu2xfw%40mail.gmail.com
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-2KfkjwOaiQCbqCnMOH0LfMUdVJouJ-uRSUFZzhqk37tg%40mail.gmail.com.
Miguel Ojeda
2018-10-09 12:26:04 UTC
Permalink
Hi Daniel,
Post by Daniel Gutson
I just read the proposal and I'm glad I'm not alone :)
Please keep in mind that there are other cases. For example, doing stuff over IO mapped memory.
This particularly may be a bug and a different thread, but a call to std::fill_n over a volatile-qualified buffer gets removed in the gcc, clang, icc and MSVC.
OTOH does your secure_val allow the value placed in registers?
Sure, and actually a vendor may be encouraged to place such memory in
registers if at all possible, since that would directly remove any
concerns about leaks from the memory or the cache; as explained in the
proposal.

The proposal does not specify where the value should be stored -- that
is one of the keys: it could even be stored in some "special" kind of
memory. Basically, the implementer decides what is the best option for
the given T and their platform/OS/etc. What is important is that they
do as much effort as possible to protect the value for the users.

The goal, in the end, is that application users have an easy way to
mark what is supposed to be protected and when such value is accessed.

Cheers,
Miguel
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANiq72mnWuMGNT27jVueGTvnk4eGNKWsMbWPJnejC1tPxhT7WA%40mail.gmail.com.
o***@join.cc
2018-10-01 09:27:59 UTC
Permalink
Post by Daniel Gutson
Again, on the DSE related optimizations.
I'm at the Ekoparty where I will show a presentation about security
vulnerabilities caused by compiler optimizations. The subject is more and
more serious (e.g. [1]).
I want to propose to allow [[nodiscard]] in individual expressions, such
as calls to memset(), std::fill_n, and assignments (DSE happens with both
memory and registers).
What's DSE?
And what's [1]?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8fa2ebcf-19c5-4b32-a8c6-9fa503010467%40isocpp.org.
Daniel Gutson
2018-10-07 04:54:23 UTC
Permalink
Post by o***@join.cc
Post by Daniel Gutson
Again, on the DSE related optimizations.
I'm at the Ekoparty where I will show a presentation about security
vulnerabilities caused by compiler optimizations. The subject is more and
more serious (e.g. [1]).
I want to propose to allow [[nodiscard]] in individual expressions, such
as calls to memset(), std::fill_n, and assignments (DSE happens with both
memory and registers).
What's DSE?
And what's [1]?
Sorry for the lack of context, I strongly suggest people to take a look at
these papers without further participating in this discussion:
https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf
https://nebelwelt.net/publications/files/15LangSec.pdf

Comments:
https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations
There are plenty of issues filed to the gcc and clang issue trackers about
this that were systematically closed as invalid. But the problem remains
and is deadly serious. I did a demonstration at the Ekoparty of an exploit
using this.
Post by o***@join.cc
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8fa2ebcf-19c5-4b32-a8c6-9fa503010467%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8fa2ebcf-19c5-4b32-a8c6-9fa503010467%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-3ow7TvHO%2B2Y9Ww12PwGRj6H5hq3aennxt2Jq7-XGLzmw%40mail.gmail.com.
Daniel Gutson
2018-10-09 12:10:00 UTC
Permalink
El 28 sept. 2018 8:13, "Daniel Gutson" <***@gmail.com> escribió:

Again, on the DSE related optimizations.


After thinking based on some feedbacks (especially from what I understood
from Florian) I concluded that the problem is bigger (value taunting) and
my attribute-based approach is not enough.
Evenmore none of the proposed solutions covers the scenarios. Moreover the
exploits have not been described AFAIK.

Thanks Florian, Miguel Ojeda and all those provided feedbacks.

I will come up with a further explanation and more complete solution in a
new thread after more research.



I'm at the Ekoparty where I will show a presentation about security
vulnerabilities caused by compiler optimizations. The subject is more and
more serious (e.g. [1]).

I want to propose to allow [[nodiscard]] in individual expressions, such as
calls to memset(), std::fill_n, and assignments (DSE happens with both
memory and registers).

Ideas? Co-authors?
--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFdMc-2UXSNGCYophb_mVhMTJBjHCWDxFekpXDY7HGY1upc4bw%40mail.gmail.com.
Loading...