December 15, 2022
On Thu, Dec 15, 2022 at 09:41:08AM +0000, areYouSureAboutThat via Digitalmars-d wrote:
> On Thursday, 15 December 2022 at 01:12:28 UTC, norm wrote:
[...]
> > Most security hacks (that I know of) are not due to C array overruns.  Those headliners that usually come from C/C++ code written >10yrs ago.  The majority of security breaches are due to human activities, people clicking on fake email links, sharing passwords, leaving computers unlocked, incorrect server and database configuration etc. Rust and @safe will not solve these real world problems.
> 
> you forget to mention.. 'and programmers blindly using third-party packages'
> 
> 'An Empirical Study on Production Dependencies in NPM' - 2022
> 
> "The problem is that developers struggle to identify what vulnerabilities may affect their software application.."
> 
> https://arxiv.org/pdf/2207.14711.pdf

+1, I have always been skeptical about the contemporary trend of using fancy package managers with hairball external dependencies that make your builds dependent on some opaque remote server somewhere out there on the 'Net that you have no control over.  Some time ago somebody also posted another article about how easy it is to conduct MITM attacks on these external package repositories to insert a malicious package / substitute a legitimate package with a malicious version.

Not only it's a security hazard, it's also a logistic time-bomb: you never know if the remote server won't suddenly vanish off the face of the internet right at the moment when you're about to release your product and need to make the final production build. (It may come back tomorrow or the day after, but deadlines would be missed, heads would roll.)  You're basically putting yourself at the mercy (and/or (in)competence) of some independent external entity you have zero control or influence over.


T

-- 
In a world without fences, who needs Windows and Gates? -- Christian Surchi
December 15, 2022
On Thursday, 15 December 2022 at 14:36:18 UTC, H. S. Teoh wrote:
> +1, I have always been skeptical about the contemporary trend of using fancy package managers with hairball external dependencies that make your builds dependent on some opaque remote server somewhere out there on the 'Net that you have no control over.  Some time ago somebody also posted another article about how easy it is to conduct MITM attacks on these external package repositories to insert a malicious package / substitute a legitimate package with a malicious version.
>
> Not only it's a security hazard, it's also a logistic time-bomb: you never know if the remote server won't suddenly vanish off the face of the internet right at the moment when you're about to release your product and need to make the final production build. (It may come back tomorrow or the day after, but deadlines would be missed, heads would roll.)  You're basically putting yourself at the mercy (and/or (in)competence) of some independent external entity you have zero control or influence over.

Any serious organization relying on DUB packages would have their own local mirror of this stuff and also pin all dependencies to specific commit hashes rather than version tags (after reviewing the code, checking digital signatures, etc.).

It's also possible to use the compilers and libraries packaged in some reputable Linux distribution. Albeit the compiler versions will be somewhat stale and the variety of the available third-party libraries will be somewhat limited.
December 16, 2022
On 16/12/2022 4:19 AM, Siarhei Siamashka wrote:
> Any serious organization relying on DUB packages would have their own local mirror of this stuff and also pin all dependencies to specific commit hashes rather than version tags (after reviewing the code, checking digital signatures, etc.).

We should have our own artifact repository as part of dub-registry.

That way we can pin versions to artifacts and not let people move things out from under other peoples feet.

But yeah, lots of work that can be done to mitigate any potential issues.
December 15, 2022
On Thu, Dec 15, 2022 at 03:19:12PM +0000, Siarhei Siamashka via Digitalmars-d wrote: [...]
> Any serious organization relying on DUB packages would have their own local mirror of this stuff

How easy is it to create a DUB mirror?  Perhaps that's one area of improvement. Ideally it should be as easy as `dub clone-repo`, though in practice of course that would be much more involved than that.


> and also pin all dependencies to specific commit hashes rather than version tags (after reviewing the code, checking digital signatures, etc.).
[...]

Tying dependencies to commit hashes instead of version tags is a good step forward.  It's not 100% foolproof, though, no thanks to the SHA-1 collision attack. (It's extremely unlikely, of course. But in theory it's possible that a malicious actor could have generated a repo containing the innocent half of a colliding pair and substituted it with the malicious half afterwards. Though probably it's not worth thinking about, unless your project happens to be a sensitive security-related one where the risk of being targeted by a sophisticated attacker is high. In which case you probably wouldn't be using random packages from a DUB repo in the first place. :-P)

Having said that, though, if you're going to be tying dependencies to specific hashes, might as well just graft the dependencies into your source tree instead.  Then you could just `git checkout` some branch or tag and be 100% assured that it will build successfully, and that the build products will be 100% identical to the last time you built that branch or tag.  Reproducibility is a critical factor in debugging -- nothing like trying to chase down a bug only to have it vanish from under you because some random upstream repo decided to upgrade their package in the middle of your debug session.


T

-- 
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald Knuth
December 15, 2022

On Monday, 12 December 2022 at 14:33:21 UTC, Siarhei Siamashka wrote:

>

On Monday, 12 December 2022 at 12:53:42 UTC, Nick Treleaven wrote:

>

I almost never use @safe: because it prevents @safe attribute inference.

Why is this a problem?

For example, template functions that are marked @safe are often overly restrictive. The safety can be inferred (and @safe unittests used to ensure they are inferred @safe). Template functions often take a type parameter that could be a type with @system operations, or an alias parameter that could take a @system variable or a @system delegate say. In those cases the template function will fail to instantiate (assuming the delegate is called). I would say @safe annotated template functions are an anti-pattern, certainly in a public API.

This is why @safe module foo; would be better than @safe: - it wouldn't override inference of @safe/@system. The only downside is then you have to have a module declaration even for simple D files.

December 15, 2022
On Thursday, 15 December 2022 at 18:48:56 UTC, Nick Treleaven wrote:
>
> This is why `@safe module foo;` would be better than `@safe:` - it wouldn't override inference of @safe/@system. The only downside is then you have to have a module declaration even for simple D files.

One really should compile dmd from source, **after** altering the dmd source in this way:

Required a module to always be annotated with @safe.

And if it is not annotated as such, the compiler provides a warning, saying -> If you want to compile an unsafe module (i.e. one not annotated as @safe), then you MUST pass -unsafe as a parameter to the compiler.

I suspect D3 (in 2045) will be safe by default though.

But one does not need to wait that long just to make @safe default .. its pretty easy to do it ;-)

January 22, 2023
On Monday, 5 December 2022 at 20:28:42 UTC, Sergey wrote:
> On Monday, 5 December 2022 at 19:57:39 UTC, H. S. Teoh wrote:
>> but it's keeping track of the *lifetime* of allocated memory.  One could say that this is proof that lifetime is a complex problem. But again it's a strong argument that the GC brings a major benefit: it relieves
>
> Thank you for interesting statistics and analysis. Unfortunately it seems that the IT community (biggest companies with largest code bases) stick with borrow-checker lifetime approach to solve those issues and not on GC.

The story with recommendations from NSA about “safe” languages is continued..
Answer from Bjarne https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2739r0.pdf
January 22, 2023
On 12/15/22 09:01, Dom DiSc wrote:
> 
> I don't think so. A search for @trusted finds both.
> But the lambda reduces the amount of @trusted code (e.g. all the rest in main() can be @safe, so you don't need to check it).
> On the contrary: I would allow @trusted blocks (so that the ugly lambda construct wouldn't be necessary anymore) and forbid @trusted functions altogether - they are simply @system.
> 
> This allows to reduce the trusted parts step by step by declaring @system functions as @save and instead mark the few lines in them that do unsafe things as @trusted - until there are no @system functions anymore and the @trusted parts don't contain any calls (except for external calls to parts out of your control because they are from unsafe languages or the source is not available - which should be avoided, unless someone guarantees* them to be save).
> 
> Best practice should be to use @trusted around as few lines of code as possible (and of course avoid @system as far as possible).
> This is because everything @trusted need to be checked manually and this is very time consuming.

This is a fallacy. All it achieves is:

- Some incomplete @safe-ty checks in code that should _actually_ be `@system/@trusted` (this part can be useful, but OTOH you will have `@safe` annotations that are fundamentally a lie).

- Unknown scope of _actual_ `@trusted`, you will have to manually check _`@safe`_ code as well, and a priori you will have no idea how much of it you have to check (this part is terrible).

It certainly does not help you minimize the number of lines you have to check.
January 22, 2023
On Sunday, 22 January 2023 at 10:08:55 UTC, Timon Gehr wrote:
> On 12/15/22 09:01, Dom DiSc wrote:
>> Best practice should be to use @trusted around as few lines of code as possible (and of course avoid @system as far as possible).
>> This is because everything @trusted need to be checked manually and this is very time consuming.
>
> This is a fallacy. All it achieves is:
>
> - Some incomplete @safe-ty checks in code that should _actually_ be `@system/@trusted` (this part can be useful, but OTOH you will have `@safe` annotations that are fundamentally a lie).
If you want, you can take any @safe function that contains a @trusted block as something to be completely manually checked - than this system won't make any difference to the current one.

But I'm pretty sure most @trusted blocks didn't invalidate the safety of the whole function, because they ARE only a wrapper around a @system function call, and it is sufficient to check manually, that the system function is called in a safe way, e.g. with valid safe parameters.

Most prominent are wrappers around C string functions, that can be considered safe if the parameters are checked to have valid length, don't point to zero and are indeed null-terminated.
This kind of @trusted blocks are (at least in my code) the vast majority.
Only very seldom I do something complicated and unsafe that I really do trust - and then I simply mark the whole function with a @trusted block.
The difference is only

@trusted fn() {

};

vs.

@safe fn() { @trusted {

} };

But what we gain is that @save/@system is then a binary attribute and not a cumbersome tri-state anymore. Everything is either safe or not.

> - Unknown scope of _actual_ `@trusted`, you will have to manually check _`@safe`_ code as well, and a priori you will have no idea how much of it you have to check (this part is terrible).

Why is this terrible? In worst case you have to check exactly as much code manually as you do today. But in most cases you have to check much less.

> It certainly does not help you minimize the number of lines you have to check.

Again, why? Most @trusted blocks are isolated one-liners.
January 22, 2023
I tend to agree with Timon. We've been using the @trusted lambda thing for years now, and it just looks like a code smell. For example:

@safe void merry()
{
    @trusted int* p = malloc(10);
    ...
    @trusted free(p);
}

Has this improved anything? I doubt it.

Wouldn't it be far better to encapsulate the malloc/free pair as the allocation for an object with certain behaviors, and thus encapsulate the object rather than the operations?