244 karma · joined July 1, 2020
Edit. This is the strategy Chrome sandboxing uses: a hardened runtime (JS/WASM) inside a seccomp enclosure. https://chromium.googlesource.com/chromiumos/docs/+/master/s...
* A wide ecosystem of mature language toolchains.
* Simplicity: JS implementation contain sophisticated JITs, which are harder to prove correct compared to a simple ASM translator.
* Portability: not tied to a specific HW architecture.
Fake: A replacement module that behaves like a production module, but with certain simplifications, for example in-process vs. using rpcs, or simply cleaning up the filesystem after usage. For example, https://github.com/tk0miya/testing.postgresql. "automatically setups a postgresql instance in a temporary directory, and destroys it after testing".
Furthermore, these are external dependencies that can't be run in-process. If a dependency can be run in-process (aka library), there is no justification to ever mock it. I've even seen codebases that mock their own class B in order to test class A. Run the production code already. Ban mocking libraries.
While it is difficult to design a secure procurement chain all the way to the SiO2, we could at least design simple enough hw/sw systems for which formal verification is an economical option. And then force government entities to use formally verified systems instead of the bug ridden crap most shops, especially the sw ones, have to ship under intense deadline pressure. The market has led us into a broken local optima, no way to get out short of state level action.
"Our recommended [language extensions] defaults are: AutoDeriveTypeable BangPatterns BinaryLiterals ConstraintKinds DataKinds DefaultSignatures DeriveDataTypeable DeriveFoldable DeriveFunctor DeriveGeneric DeriveTraversable DoAndIfThenElse EmptyDataDecls ExistentialQuantification FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving InstanceSigs KindSignatures LambdaCase MonadFailDesugaring MultiParamTypeClasses MultiWayIf NamedFieldPuns NoImplicitPrelude OverloadedStrings PartialTypeSignatures PatternGuards PolyKinds RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving TupleSections TypeFamilies TypeSynonymInstances ViewPatterns"
39 language extensions just to get started. This screams 'incredibly complicated', even if perhaps reality is rather more mundane. Consider the 40th language extension: GradualTyping, so perhaps those that would rather write code about data than about types using a half baked and evolving type language (which taken to its logical conclusion will have to become a full fledged theorem prover in the Coq / Idris / Agda / Lean lineage anyways) could get their jobs done.
Wish you guys all the best!
A. Pure functions + immutable data structures.
B. Expressive type systems, all the way to compile-time metaprogramming and dependently typed proofs.
Writing programs in style A. is tremendously valuable. Expending too much effort in the fine points of the type system, which invariably is simultaneously both under-expressive and over-expressive, is a complete waste of time. Some critical projects require high defect-free confidence, and for those it's legitimate to go full in formal proofs and take the 10x-100x productivity slowdown. For mere mortals, documenting the structure of the data (json) manipulated by the respective functions suffices.
// on exit the finally fn will be called with 'x' as an argument.
with (Type x: create(args); finally (Type x) -> cleanup(x)) {
// safely use x, throw at will.
}
Re C++ and exceptions, there is an additional layer of wrinkles: throwing exceptions from ctors or, worse, dtors. Herb Sutter used to have a loooong list of what can go wrong in such situations back in the day. Explicit error codes happen to make it impossible to write ctors / dtors that can enter an error state by virtue of the fact that there is no way to return the error. My suspicion is that this is 50% of the reason of banning C++ exceptions in solid C++ style guides. // bad
NotifyIcon CreateNotifyIcon()
{
NotifyIcon icon = new NotifyIcon();
icon.Text = "Blah blah blah";
system.Display(icon);
icon.Icon = new Icon(GetType(), "cool.ico");
return icon;
}
Which would make noticing the coding error quite a bit easier, as we are passing an obviously incompletely initialized object to a third party. As presented, the code presumably is intended to be used like so: NotifyIcon icon = CreateNotifyIcon();
system.Display(icon);
which works in both versions. If 'icon.Icon = new Icon(GetType(), "cool.ico");' throws, then the NotifyIcon is never displayed.As presented, this is hardly an argument that explicit error passing code is better at detecting bad code than exception based code. His other article, https://devblogs.microsoft.com/oldnewthing/20040422-00/?p=39..., is making the point a bit more clearly.
The point itself is half-sound. While it is true that with exception based code, it is hard to distinguish which statements may fail, the real issue is about correctly releasing resources. Assume that every statement can fail, and use some form RAII to manage resource cleanup. The exact content of RAII is hard to glean in both explicit error code and exception based code, as it depends on how the specific third party API acquires/releases resources. Though APIs can be organized to essentially force the use of RAII, even if popular but ancient APIs like POSIX file system are not designed that way.
The real language design issue is that Java/C# mechanism for running cleanup code 'try {} finally {}' a. fails to pass through a handle to the resource that needs cleanup and b. is not scoping the lifetime of the resource that needs cleanup. Furthermore, the standard API makes no effort to provide RAII constructs for correctly managing resource lifetimes. Those language ecosystems actively steer people towards writing bad code. Exceptions may be fine, but the lack of language supported RAII is definitely poor language design. For better language design, exception based Python offers 'with' mechanism and error code based Golang offers 'defer'.
// bad
NotifyIcon CreateNotifyIcon()
{
NotifyIcon icon = new NotifyIcon();
icon.Text = "Blah blah blah";
icon.Visible = true;
icon.Icon = new Icon(GetType(), "cool.ico");
return icon;
}
// not-bad
NotifyIcon CreateNotifyIcon()
{
NotifyIcon icon = new NotifyIcon();
icon.Text = "Blah blah blah";
icon.Icon = new Icon(GetType(), "cool.ico");
icon.Visible = true;
return icon;
}
What is the problem with the first version and how is the second version fixing it?Sadly, this is of limited use. Defense against fingerprinting is like herd immunity. If everybody else already has a unique fingerprint, there is not much an individual can do to avoid being uniquely identified as well. At most one can spoof one other unique individual. Plus the EFF recommendation is 'latest Chrome on Windows' which is a moving target.
Would be nice if the EFF site in OP would recommend an agent id to spoof to, at least that would help building a small, but non trivial herd of indistinguishable users. And then a popular extension like uBlock Origin would track this agent id and set it by default for all its users.
Edit: list of top UAs:
https://techblog.willshouse.com/2012/01/03/most-common-user-...
> Your browser fingerprint appears to be unique among the 2xx,xxx tested in the past 45 days.
> Currently, we estimate that your browser has a fingerprint that conveys at least 18.xx bits of identifying information.
Biggest offenders: USER AGENT and HTTP_ACCEPT HEADERS. Especially the USER AGENT is crazy, 9 digit browser version to everyone who asks?!