In Other Words
All of my arguments are correct, as you can only deflect from them.
1329 publicly visible posts • joined 20 Nov 2021
Russia has a population in the order of 140 millions. For simplicity we assume a similar age structure in NATO.
If they do all out conscription, then Ukraine and Poland don't have sufficient manpower. At least England and Germany would have to start conscription, too. Sweden and Finland will be happy to defend themselves.
Maybe this must be done, I dont have a crystal ball, either.
And this time we will not make an exception. Draft the journalists and bureaucrats first, they are typically the worst warmongers. Those who claim disabilities must serve in command centers/logistic centers/arms dumps, always ready to take a CM or ballistic hit. Age 18..60, no exceptions.
Of course we could escalate:
1.) Take out critical infrastructure deep in Russia, using cruise missiles, stealth.
1.2) Sea blockade of Russia; serious sinking of Russian surface fleet. Submarines must be dealt with, too.
2.) Fight a nasty infantery/tank/missile war in Poland, Baltics
2.2) Conscript men in England, France, Germany, Spain, Italy, USA, Canada to get the required manpower vis a vis Russia's conscription
3.) Absorb quite a few cruise missile hits on London, Berlin, Warsaw and maybe even Paris.
In other words, not as convenient as our childish warmongers want it.
Do YOU want to be conscripted as a MILAN anti tank gunner ? We have would have 200 000 openings TOMORROW.
The question of "who belongs Ukraine to" was an open question a long time ago. It could have been answered by "neutral like Finland." But diplomacy failed to make this happen, so the weapons make the decision.
From the Russian POV, there are three empires: Moscow, Anglosaxon(from Seoul to Vilnus), Beijing. The Moscovites see the Anglosaxon empire encroaching on theirs and they felt a need to make the expansion stop, as talking yielded nothing substantial.
We now have the fire burning, how to turn it off ?
After that, the Dear Leader and his Generals will have all their nice villas wiped out, the airforce destroyed, all surface ships sunk and so on. His huge army with outdated cr4ap will be hammered into pieces in three weeks.
If they dare to use nukes, well, the Americans have thousands, all of them well tested all round.
If Russia were to ever face all of NATO, it would be very asymmetrical. Russia already showed the Nuclear Card around because they know their weakness. Unlike Hitler, Putin has not inherited an industrial powerhouse. The difference in industrial power is easily 20x or more. That is, if you can quantify the technological gap in many technologies.
The main "weapons" of Russia are propaganda and cojones. That won't help against mass attacks of cruise missiles and state of the art electronic warfare. It won't help against a VW factory which is converted to low cost drones.
Cojones, we have, too.
Regarding the "burn down the world" utterings, we should strongly request the Moscovites to put the dear leader into hospital for six weeks. Or does Moscow really want to commit suicide ?
Given that both sides have had serious damage and horrible death counts; given that both sides have rational arguments (Ukraine: self-determination; Russia: strategic security) it is time to look for a Korea-style solution.
Freeze the war at the current frontline.
The alternative is a deadly idealism, a continuation of the meatgrinder.
Was it Mrs NULAND or was it Mr PUTIN ? Nobody really knows anymore.
I get it, I am wrong in theory. But not in practice for the OSs/environments Sappeur currently targets. I specifically said so from the beginning. Windows, Linux, BSDs, MacOS, Solaris, HP-UX, AIX - they will all reliably generate a SIGSEV(or equivalent) when accessing a NULL pointer. That's deterministic behaviour as required for Memory Safety.
The other environments (small embedded systems without an MMU) I currently do not target.
I never claimed the "address 0 invalid space" exists in embedded systems, rather I specifically claimed this to exist for all sorts of modern Unix(es) and Windows. This invalid address space exists, has been existing for a long time and will detect NULL pointers reliably and at zero runtime cost.
ALSR will randomize addresses outside the "invalid space" and does not matter here.
Again, please post a demo program for Windows, Linux or MacOS, which will prove me wrong.
In this case the software engineering organization must PROVE this cannot happen. This usually means the process cannot allocate or deallocate heap memory(except during boot-up and stand-down), as the heap is too unpredictable for hard realtime systems.
Of course the generation of this Proof might be hard to do by hand. If the language support non-nullable pointers the proof is easier. A source code inspection by experienced engineers combined with all the testing of the V model might(or not, if code is too complex) be able to generate this proof. Any relevant source code change must trigger a regeneration this proof.
Also see SPARK Ada and similar.
Please see my other post with the test program in C. The invalid memory space starting from 0 is actually many Gigabytes in size on 64 bit machines. This means that any NULL pointer to an object smaller than that will generate a SIGSEV exactly where the bug is. A debuggable core fil will be dumped. Sappeur Arrays are a not affected by this limit.
Conclusion: for all remotely sane (object size lower than 1000 000 000 octets) programs NULL pointers will generate a SIGSEV.
If you do not believe me, please perform your own tests and prove me wrong.
Please use the following test program to see that in practice your concern is not an issue. Apparently the "memory guard space" is in the order of 140 735 371 892 940 octets. (Linux 64 bit).
On MacOS, it seems to be about 6000 000 000.
This also aligns with my practical experience writing software in C, C++ and Sappeur.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct MemTest
{
char buffer[650000];
char* str;
char buffer2[6500000];
};
int main(int argc, char** argv)
{
int x;
char* str1 = malloc(100000000);
printf("adresse von str1: %lli\n",(long long int)str1);
printf("adresse von x: %lli\n",(long long int)&x);
strcpy(str1,"abc");
printf("%s",str1);
free(str1);
str1 = NULL;
struct MemTest* mtp = NULL;
mtp->str = malloc(10);
return 1;
}
As I wrote above, I have never seen what you describe happen in the real world. (On Unixes and Windows)
And of course I had plenty of cases of forgetting to initialize a pointer during a development session and always got the determinsitic SIGSEV exactly at first dereferencing.
Your are right though that it is a problem in contrived examples.
During my 20 years of software engineering experience on HP-UX, AIX, Solaris, Windows, MacOS and Linux I never had the problem of a NULL pointer not leading to a deterministic crash, exactly where the FIRST pointer dereferencing happens.
This is because these operating systems by default allocate "invalid" MMU pages from address 0 to something like address 64000. In the example above, the planet struct would have to be bigger than 64K to lead to an undetected error.
This is not the case in embedded systems, though. Sappeur currently targets "only" all kinds of Unixoid and Windows OSs with MMUs. From Solaris to ELBRUS Linux. One key assumption of Sappeur is that its smart pointers are initialized to NULL and will create a deterministic SIGSEV (or Windows equivalent) on dereferencing a NULL pointer. This assumption is important for performance, safety and security reasons.
So you are "right" that this mechanism is not safe and secure for "huge" Sappeur classes.
In 10 years of programming in Sappeur I never had such a case. Creating a class with 64K size per instance is rather unusual and I never needed this. In case of arrays, which can of course be much bigger than 64K, the SPRArray._sz member is at the beginning of the data structure, well within the first few dozens of octets. Each array access will be preceded by accessing _sz for index checking. This will then generate the deterministic SIGSEV and a debuggable core.
So in theory you have a point, but not in the real world I have seen. In a future version of Sappeur I might consider adding a check that classes cannot be larger than 64K, thereby eliminating the problem in principle. Larger classes would then require non-nullable pointers, something also to be added to the language.
Again: you have a programming error, which can lead to RAM exhaustion. An attacker comes along and triggers a SIGSEV from that. Program stops, core is dumped. Then you, the senior engineer, attaches gdb and finds the error location. Very soon you have found the bug, fixed it and compiled the new program version. System running again after 33 Minutes.
No information disclosed to attacker, no effectors manipulated, downtime 33 Minutes. Great.
planet* P = new malloc(sizeof(planet);
p->weight = 1E30;
That will fail deterministically, debuggably and SECURELY(SIGSEV plus core dump) on all IT operating systems I know of, if memory is exhausted. Of course you can (and sometimes should) check the return value of malloc, but if you do not do it, you will not have a security problem. That was my point.
A determinstic(read: easy to debug) crash from a DOS attack is benign as compared to Malware Injection and Reconnaissance For Months.
The only exception to this would be military communication systems, where downtime could mean losing a war. As far as I know, they have their software engineers "embedded" or on very short call. Their most important systems are created by "themselves", which means they can fix any DOS issue on very short notice.
If you create an http server for a "known population of clients", then maybe you do not need to care about DOS attacks. Note that this is not true for subversion opportunities, as you must always assume one of your intranet machines being compromised.
Actually, this is how things like Oracle are operated - they are locked behind a firewall as they would be easily hacked if exposed to the wild world of internet or even the entire intranet.
The management of RAM allocation, database connection numbers, file handles, number of threads etc must be managed by the application programmer. There is no sensible way an automatic runtime mechanism can do this for the app programmer. Except, of course, stopping the thread or program upon resource exhaustion.
So - the application programmer must think about all the resources he allocates in his program. For example, an http server must reject too many parallel requests(Code 429 Resource Exhausted). An application using database handles must limit the number of database connections by some sort of pooling and semaphores. No automatic mechanism on the runtime/language level can replace programmer reasoning here(except maybe some sort of database pool which blocks until a connection becomes free).
Memory Safety is not the paradise of programming, it "just" eliminates an ugly kind of cancer.
Software Engineering is a highly complex craft+science with lots of aspects. If it were simple, we would not earn good money on it.
In all the above languages, you will get a deterministic crash if heap allocation fails. You either get a NULL pointer from malloc() or new or some sort of OutOfMemoryException. Accessing a NULL pointer typically creates (some sort of) SIGSEV and stops the program. OutOfMemoryException typcially stops the thread.
This is exactly what you want. A deterministic, debuggable crash from a programming error/cybernetic attack. Much better than Silent Subversion from e.g. a buffer overflow.
How else could an out of memory condition be handled ?
(this applies to Windows, Linux, BSD, HPUX, Solaris, AIX, but maybe not to embedded systems)
The idea of a smartphone was also envisioned by HP Labs in the 90s. But then the large-than-life Bill Hewlett and David Packard died. There was no replacement for their engineering, production, research and operations experience. The MBAs could only slash the brain and optimize the economic side. "Optimization" meaning they would kill HP technologies and sell MS, SAP, Oracle, Intel products instead.
So the MBAs could not imagine the great value of a smartphone. They had fired all the engineers who could build it.
Steve Jobs could imagine and had the engineers on board. He made it happen.
Having said that, there are plenty of opportunities and strong companies out there. Apple is doing great both technology-wise and economically. Unlike IBM, they understand that mechanical design, GUI appearance and usability matters. Then there are hundreds of small companies who need seasoned IT experts.
Pump out dozens of applications and while you wait for the response, learn something new. A new language, HTML, a new framework, a new type of database. Learn about the V Model, there will be enormous work in auto, aerospace, rail and medical - as soon as they actually do the work according to the book. Learn effective presentation, if you haven't yet. Write a blog about something technologically relevant...
1.) Forget the BS they told you about "lifelong job security". No commercial company can do that. Not even Google. It's a br4inf4ck to stop you from looking for an external career move.
2.) "creative destruction" is a very real thing, like it or not. Microsoft, Google, and Amazon ate the business of HP, IBM, DEC, Unisys, Fujitsu. These "old" IT companies have a calcified brain and cannot quickly adapt to new challenges. Even worse, they cannot use their own great ideas, because they would threaten existing business. For example, HP's BIRNBAUM was thinking about Cloud Computing back in the 90s. Amazon made it happen in the 2000s and HP is now on crutches.
2.2) Because the business of the old companies evaporates, their employees can no longer be paid at a proper rate. Macro-economically speaking, they must transfer from the old companies to the new ones.
3.) Never stay too long at one company, so that you know how to sell yourself and get interviews. Not applying for 20 years will deteriorate your self-selling skills.
The macro processor of C is just one aspect of the language. There exists a modicum of type safety from a very basic type system in the C language. It just is not as comprehensive as it should be. Too many "undefined behaviour" cases.
Note that in C++ you can use a powerful macro processor to replace the convoluted STL system. And its crazy error messages.
E.g. use m4 to generate/instantiate container classes on the harddrive. If you have a bug, then you will get concise error messages inside the generated code. Much better to understand for mankind. If you are a masochist, you can even use cfront macro processor to perform this.
One could even perform generic programming in C using this approach (e.g. a typesafe generic_sort() instead of the void* abomination).
According to your assertion NOBODY should generate C code, as we are all "fallible". The best software engineers write a bug then and now. The most advanced static checker tools, unit testing, module testing, HIL testing and valgrind runs cannot find all of the bugs. We have seen them in the Linux Kernel, in VxWorks, in Windows kernel and user mode, in loads of application level programs developed by seasoned experts.
The first time Unix userland tools were run under valgrind checking were a revelation. Hundreds of bugs, which existed for decades in millions of actively used systems.
Here is a list of the memory safety issues of C http://sappeur.ddnss.de/SappeurCompared.html
I would argue that you are mostly correct, the amount of C code men generate should be very limited. There are NO perfect software engineers. There are only Code Generators (such as the Sappeur compiler) which are very close to memory safety perfection.
They either updated the model, or the exact wording of the queries is super important. I would NOW grade
"tell me the difference between the Osprey V22 and the Dornier 31" - 4. One faulty sentence "The Do 31, on the other hand, used jet engines for VTOL capabilities and did not have the ability to fly like a fixed-wing aircraft."
"write the c++ code for Enigma" - 5. Text is kind of OK, but the code is completely wrong.
#include <iostream>
#include <string>
const int NUM_WHEELS = 3; // Number of wheels in the Enigma machine
const int ALPHABET_SIZE = 26; // Size of the alphabet
// The mapping of each letter of the alphabet to another letter
// For example, mapping[0] is the mapping for 'A', mapping[1] is the mapping for 'B', etc.
int mapping[ALPHABET_SIZE];
// The current positions of each wheel
int wheel_positions[NUM_WHEELS];
// Initialize the mapping and wheel positions
void initialize() {
// Set up the mapping of each letter to another letter
// In this example, we just use a simple rotation of the alphabet by 3 letters
for (int i = 0; i < ALPHABET_SIZE; i++) {
mapping[i] = (i + 3) % ALPHABET_SIZE;
}
// Set the initial positions of the wheels
for (int i = 0; i < NUM_WHEELS; i++) {
wheel_positions[i] = 0;
}
}
// Encrypt a single character using the Enigma machine
char encrypt(char c) {
// Rotate the wheels
for (int i = NUM_WHEELS - 1; i >= 0; i--) {
wheel_positions[i] = (wheel_positions[i] + 1) % ALPHABET_SIZE;
if (wheel_positions[i] > 0) {
break; // Only rotate the next wheel if the current one has "carried over"
}
}
// Get the index of the character in the alphabet (e.g. 0 for 'A', 1 for 'B', etc.)
int index = c - 'A';
// Use the mapping and the wheel positions to encrypt the character
int encrypted_index = (index + mapping[index] + wheel_positions[0]) % ALPHABET_SIZE;
// Convert the encrypted index back to a character and return it
return 'A' + encrypted_index;
}
// Decrypt a single character using the Enigma machine
char decrypt(char c) {
// Get the index of the character in the alphabet (e.g. 0 for 'A', 1 for 'B', etc.)
int index = c - 'A';
// Reverse the encryption process to decrypt the character
int decrypted_index = (index - mapping[index] - wheel_positions[0] + ALPHABET_SIZE) % ALPHABET_SIZE;
// Convert the decrypted index back to a character and return it
return 'A' + decrypted_index;
}
int main() {
initialize();
std::string message = "HELLO WORLD";
std::cout << "Original message: "
I have to concede I was impressed for the first few times of using ChatGPT. But then I grew demanding and tested
A) "tell me the difference between the Osprey V22 and the Dornier 31". The result was catastrophically wrong, as it declared the Do 31 being a HTOL aircraft. That would be a 6 in German grading.
B) "write the c++ code for Enigma". The result looked promising at first, until I discovered that the most important ideas were completely lacking. Grade 5.
Given the low complexity of AI systems as compared to "100 billion neurons connected to 10000 other neurons each", I should have known it from the beginning. The human brain is still one of the most powerful information processing systems we know* of. Silicon is on the level of worms at the moment.
In other words, smart teachers will use chatGPT to set up dangerous traps for lazy students.
*Elephant brains can compete on numbers, but I maybe not on structure.
PS: Now the response to the Do31-V22 query seems to be correct. Did they update their model ? Or did I use different wording then ?
There are cases where a NULL simply cannot be handled. Certain pointers MUST be non NULL, or the algorithm will fail. But it MUST be active at a very high availability rate (one instance in 1 million years or similar). Because it is a flight control system and cannot simply be turned off or restarted. If the compiler can guarantee that for the software, the organization can put more effort on the hardware side (which has physics- and chemistry-related failure rates).
Some high performance aircraft are unstable By Design and you cannot "use direct law" in case the software "has issues".
In the IT sphere, you are more or less right. A NULL pointer causes a deterministic, debuggable stop of program. Service will be stopped for an hour or so. Customer uses cash to buy a cup of coffee and comes again later to run the service again.
In other spheres such as auto, rail, aerospace and medical, you cannot just "stop the process and debug it". Imagine getting a NULL pointer inside an ABS brake algorithm, while the driver hits the brake pedal. How would you handle this as a software engineer ? Restart the process and maybe get another NULL pointer a few milliseconds later ? No, you must prove there will never be a NULL. One proper way to do this is to have the type system+compiler assuring this.