Hacker News new | past | comments | ask | show | jobs | submit | copper_think's comments login

The author mentions the screen being corrupted when a DOS prompt is opened in windowed mode. This can happen because the DOS prompt runs in a separate VM (in V86 mode), and makes calls into the VGA ROM BIOS via INT 10h. The VGA ROM BIOS on this machine is probably a wrapper over VBE; that is, it probably contains IN and OUT instructions that talk to the VBE I/O ports, 0x1CE and 0x1CF. These reads and writes from the DOS VM will, by default, be allowed to reach the physical hardware if they are not virtualized by the VMM.

This is a common problem that authors of Windows 3.x/9x display drivers had to handle, although the specific I/O port numbers to be virtualized vary by graphics adapter. There are samples in the Win95 DDK that show how to use the VMM services Install_IO_Handler and Enable/Disable_Global_Trapping to set up I/O port traps, and VDD_Get_VM_Info from within the trap handler to determine the VM that currently owns the CRTC. This allows the trap handler to reach a decision about whether to allow an I/O to reach the hardware, or to virtualize the access in some way. A good virtualization policy to start with is probably just to drop any writes from non-CRTC-owner VMs. Any additional needed complexity can be added from there.


So, it's just enantiomerically pure S-ketamine - not really a new drug discovery. The drug is already around as an anesthetic but it is almost finished with the FDA's approval process for treatment-resistant depression. When used as an anesthetic it is administered intravenously, but the anti-depressant formulation is a nasal spray. Cool! That definitely makes it more accessible.

I wonder if J&J got a patent on S-ketamine? The patent system is often abused this way. First you sell the racemic mixture, then when that patent is about to expire, you start selling a new product that is just the active enantiomer. And you can tell customers that it's new and improved: that you only need to take half as much! See Prilosec/Nexium, Celexa/Lexapro, etc.

Although, maybe it's difficult to manufacture just the one enantiomer, at scale?


Why couldn't someone else jump ahead and patent S-ketamine first while the racemic mixtures is being sold?



It's even more confusing: R-ketamine is the more effective enantiomer, with less dissociative effects.


Sweet, I like that J&J is using S-ketamine then. I think the dissociative effects of ketamine are fantastic and beneficial, even though they can be surprising. At a low dose it likely won't be an issue.


Personally, I have no issues with the dissociative effects per se. However, studies have determined that they aren't related to the antidepressant effect. Fwiw, a full clinical dose feels like ~1/4 of a 'rail'. There's no introspective trip here, just slight drunkenness.

(Incidentally, we have some evidence that the metabolite that causes the effect can be blocked via concurrent CBD administration - without reducing the dissociative effect)

The standing appointment to get slightly high for a couple of hours every three days does get inconvenient (though it's not as problematic as the resultant insomnia). I expect esketamine will be more so, for less antidepressant effect. And, being a controlled substance, I'm concerned I'll be unable to increase my dosage to make up the difference.


People seem to still be arguing about that - [1] and [2] argue that they're directly correlated in ketamine treatment, and I can't begin to guess what research on {ar,es}ketamine and metabolite efficacy is going to produce when one of these becomes readily available.

[1] - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4065787/

[2] - https://www.ncbi.nlm.nih.gov/pubmed/29501990


What is the value that private equity and/or VC are adding to dermatology? I guess what I'm asking is, why would the physicians be interested in sharing some portion of their income with these non-physicians?

Medicine, like other guild professions like law, dentistry, and accounting, is an enterprise which seems to naturally fit the partnership model instead.


Medicine is a market for lemons, so reputation/brand is important. Many good doctors are full up on patients, but if they can convince you that an unknown doctor in their practice is just as good/under their supervision, they can pocket some of those gains.

This doesn't really require private equity, but PE is providing a way to get a lump sum for this to doctors, and milking that cash cow.

There is also a growing remote/virtual dermatology sector which can see gains from technology, but I doubt PE is involved.


There is a strange bit about being a doctor or lawyer -- you aren't allowed to for a C corp for your own practice. However, if someone else forms the corp and you work for them, then you get all the protections of a C corp, as long as you don't own the majority share.

So one thing they add is legal protection.


> There is a strange bit about being a doctor or lawyer -- you aren't allowed to for a C corp for your own practice.

1. In at least some U.S. jurisdictions (and possibly all), lawyers' practices can indeed be set up as corporations; my former firm was an example. The individual lawyers in the firm are still personally liable for their own malpractice and for that of any junior attorneys and/or staff whom they supervise. The corporate form does protect them from personal liability for the office lease, etc., unless they've personally guaranteed the lease, which is not uncommon. (Don't know how it works for doctors but I assume it's similar.)

2. "C corp" is an income-tax classification; AFAIK it has nothing to do with non-tax liability.


C Corp is a legal entity classification, along the lines of S Corp, LLC, partnership, and sole proprietorship. What might be confusing is that S corps can use pass-through taxation or retained earnings (C Corp) depending on what the owners choose. There are various forms of partnerships with different levels of liabilities to the partners: general partnership, limited partnership (LP), limited liability partnership (LLP), etc. Partnerships generally provide much less protection than a C Corp.


I'm sure there is insurance cheaper than 50% of all profit.


2 docs +1 guy forms a corp with shares ratio 48-48-2, and done?


So find a doctor you trust from medical school, and you hire him for your C-Corp and he hires you for his?


The same thing they add to any other business: Better management, efficiency, etc..

I don't think any profession 'naturally fits the partnership model'. Some professions have simply managed to enshrine protectionism for themselves into law. There's precious little evidence that this is in any way beneficial for consumers and serves to do anything other than enrich the members of the professional guild at the expense of the public.


The value add is an enthusiastic pursuit of profit. Ownership by a collection of doctors drives lower margins/profits than ownership by a private equity firm. Economies of scale can also help, but that’s not the driving reason behind PE acquisitions. There’s a degree of good faith/naïveté when medical providers and pharmacies bill insurance providers. PE firms can leverage this expectation and push for increased costs with little, if any, additional overhead.


A kind of commitment device so that doctors can ensure their fellow doctors will act unethically without having to do the enforcement themselves.


When you've got 10+ doctors sharing the same building & infrastructure etc then it starts looking more like a classic business. Accounts receivable department etc


Simple economics of scale. centralizing a highly effective management and financial instruments create a lot of value, often called a roll-up strategy. a company worth 1 merged with a company worth 1 is typically worth more than 2.


Apparently for younger doctors, access to patients.

That is, joining an existing practice is more immediately rewarding than trying to establish an independent one.


I am a general surgeon employed by a hospital system in the southeast.

PE / VC don't add anything other than trying to skim a profit off the top of medicine, like any other capitalist. Dermatology is a lucrative practice. They don't have to work in hospitals, so they set their own hours. VC/PE's are doing the long game - purchase a practice (dermatology / anesthesiology, orthopedics ) and reward the current partners who basically get to receive compensation for their future earnings. In return, the current partners accept a lower salary going forward. Lucrative with guaranteed $$$ for senior partners with a few years left to practice. For new partners not so much. And definitely not for new hires. The problem is that the cost of establishing a new practice is overwhelming. You can plant a stake as a new physician in a town, but then you have to rent an office / furnish it / equip it / and employ people without any guarantee that you will get patients.

Or, when you graduate with $300k debt, you take the job that pays you $200k / year guaranteed with no risk, but accept the fact that you will be earning less than you generate. And I'm sure there's a non compete clause (I have one).

What will happen, over time, however, is that less and less people will choose that subspecialty, just like what happened to pilots.

Of course, then the VC/PE will just close shop and walk away.

In general surgery, our reimbursements have been lower than any other surgical subspecialties for years, but our saving grace is that you really can't have a hospital without a surgeon. Here in SC, there are ZERO self employed general surgeons. 30% of what we do are urgent/emergent interventions, and tons of people here in SC have either medicaid or no insurance. When I became a hospital employee, my salary tripled. Before that, if I made > $150k that was a good year. And that's 80 hour work weeks.

Because that was typical around the nation, general surgery went from being one of the most competitive residencies to one of the least. My senior partner (10 years older) was top 5% of his class. I was top 25%. For about 5-10 years, all you needed to get a residency spot was to graduate from medical school. It's recently become more competitive, probably bc most of us are employed, boosting our salaries.

Hospitals make their money from the facility fees. I do all my surgeries in my hospital system's hospitals, not the competitor's hospital.

Dermatology is one of, if not the hardest, medical professions to match in, because for whatever reason, their reimbursements are high.

For example, if I do a laparoscopic appendectomy on an 80 year old, I get $623 (CPT 44970). They'll spend a couple of days in the hospital which is not chargeable by me bc 90 days of post op care is included in the fee.

A dermatologist that cuts off a 1.5 cm skin cancer in his office gets $251 to cut it off (CPT 11602) and $307 to close the wound (12032). No nights / weekends / and pretty stressless procedure (to me).

Anyway, VC/PE want some of that revenue


So is it usually the case that whenever you see a group run medical practice, in comparison to a solo practice, that the facilities are managed by some sort of larger VC/PE group, assuming they are a private,for-profit organization rather than a hospital owned by the city or local university?

The business side of healthcare is fascinating and somewhat terrifying once you follow the money and see how this correlates to positive patient outcomes. I hope more researchers are willing to study this phenomenon without fear of losing career prospects.


no. Some are a conglomeration of private practices that joined to better negotiate with insurance companies, some are owned by other entities, some are independent. My group was self employed up until 5 years ago, but no insurance company would talk to us to give us a raise because they said we were so small (and wouldn't drop from being a provider). They didn't look to see that we didn't own a lab, a CT scanner, a surgery center, etc... They just knew we had no leverage. Now, my colleagues that remain independent say that insurance companies ask them what can we do to keep you independent? b/c when a hospital owns all the physicians in a county, they pretty much get the upper hand in the negotiations.

Basically, it's a bunch of business people making maneuvers to try and extract as much money from the system as possible, which is why it's >$30k / year to insure a family in the USA. This makes small businesses unable to compete against companies located in socialized medicine countries, in my opinion. It also makes it impossible to compete against a business that does not offer insurance to their employees.

Eventually, we'll go single payer, bc it cannot continue at this rate.

PS - Any non profit organization has to publish their tax returns. Search Form 990 and the non profit name to pull it up. All non profits have to publish the top 20 earners - some will be administrators and others will be physicians.


you should write a more extensive article on this, you explain it extremely clearly and the public's respect for your profession will mean that people will listen.


Thanks for sharing this. It was a great appendum to the article and useful to understand the practicalities of how some surgeries/appointments in the USA medical system are funded (and how some medical practices/clinics are private equitied).


Application Verifier is a feature of Windows for developers to use to check program correctness. Bruce says he turned on Full Page Heap, which makes every allocation go on a separate page, and tries to line it up so that the next page is not readable or writable. The idea is, if you go past the end of your memory allocation, the CPU raises a protection fault, and you catch the memory corruption bug at its source. Application Verifier can also do other things, like raise an error if your program ever passes an invalid HANDLE to a Windows system call.

Application Verifier is turned on by process name (i.e. "explorer.exe"). I think most of the time, developers turn on an Application Verifier feature, start just one process by that name, and then verify. But Bruce turned it on for a short-lived process that runs in a large build. So it runs thousands of times, and he hit this problem. It sounds like a great thing to fix, but I don't think it affects most developers using Application Verifier, and it definitely doesn't affect 'normal people' who are just using Windows on their laptop or desktop.


I do remember a coworker at another company complaining that their hard drive was filling up and it turned out the problem was the App Verifier log files. In that case the individual log files were enormous so a few dozen (hundred?) runs of the program under test was enough to be a problem. Different, but related, and perhaps more common than the problem which I hit.


If the log files aren’t cleaned up, you’ll hit this issue even if you don’t run it 30k times in a minute. I ran into a very similar problem with pytest (python) creating sequentially numbered temp dir/files under /tmp on linux. Result: full / partition.


My version of this - OS (Linux) crashes due to overclock stability testing filled EFI NVRAM, and I had to manually delete the crash dumps after running into puzzling issues later on. Apparently it was possible (on some hardware, at least) for the automatic dumps to brick your computer: https://bugzilla.redhat.com/show_bug.cgi?id=919485


At Microsoft the compiler team (Visual C++) and the Windows team are joined at the hip. I'm sure the same was true at Sun. This can lead to good decisions about undefined behavior that I hope would make Linus smile.

I recently learned of one such good engineering decision (I hope I'm remembering it correctly). Let's say you have a struct with an int32 and a byte in it. That's 5 bytes, right? But the platform alignment is a multiple of 4 bytes, so there's 3 bytes of padding (sizeof the struct is 8 bytes). If we stack-allocate an array of 11 of these and zero-initialize with = { 0 }, what would you expect to see in memory after initialization?

It turns out the answer was that the first element of the array would have its 5 bytes zeroed, but the 3 bytes of padding would be left uninitialized. Then, the remaining 10 elements of the array would be zeroed with a memset that actually zeroed all 80 remaining bytes. It sounds weird but this is a legal thing to do from the standard's perspective. All they're obligated to zero out are the non-padding bytes. This UB was leading to disclosure of little bits of kernel memory back into user mode because Windows engineers assumed that = { 0 } was the same as leaving the variable uninitialized and then memsetting the whole thing to zero. Nope!

The compiler team fixed this by always zeroing out padding too. Problem solved. There are some cases where it's not quite as fast. But it's the right engineering decision by the compiler team for their customers, both internal and external.


Minor nitpick, the zeroing (or lack thereof) of the padding is not undefined behavior, it's unspecified behavior. Undefined behavior and unspecified behavior often look and perhaps behave the same to the programmer, but have semantic differences. In the face of undefined behavior, the compiler is allowed to do pretty much anything it wants (including formatting your hard drive and/or launching the nukes). With unspecified behavior, the compiler implementer must make a conscious decision on what the behavior will be and document the behavior it will follow.


> With unspecified behavior, the compiler implementer must make a conscious decision on what the behavior will be and document the behavior it will follow.

No, what you described is implementation-defined behavior.

It may be confusing, but here's the breakdown of different kinds of behavior in the C standard:

* Well-defined: there is a set of semantics that is defined by the C abstract machine that every implementation must (appear to) execute exactly. Example: the result of a[b].

* Implementation-defined: the compiler has a choice of what it may implement for semantics, and it must document the choice it makes. Example: the size (in bits and chars) of 'int', the signedness of 'char'.

* Unspecified: the compiler has a choice of what it may implement for semantics, but the compiler is not required to document the choice, nor is it required to make the same choice in all circumstances. Example: the order of evaluation of a + b.

* Undefined: the compiler is not required to maintain any observable semantics of a program that executes undefined behavior (key point: undefined behavior is a dynamic property related to an execution trace, not a static property of the source code). Example: dereferencing a null pointer.


Nice comment! Here are the excerpts from n1570.pdf[1] with some punctuation added by me to compensate for the limited formatting support on this forum:

§3.4.0: behavior: external appearance or action

§3.4.1: implementation-defined behavior: unspecified behavior where each implementation documents how the choice is made. EXAMPLE: An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.

§3.4.2: locale-specific behavior: behavior that depends on local conventions of nationality, culture, and language that each implementation documents. EXAMPLE: An example of locale-specific behavior is whether the islower function returns true for characters other than the 26 lowercase Latin letters.

§3.4.3: undefined behavior: behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements. NOTE: Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). EXAMPLE: An example of undefined behavior is the behavior on integer overflow.

§3.4.4: unspecified behavior: use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance. EXAMPLE: An example of unspecified behavior is the order in which the arguments to a function are evaluated.

[1]: WG14 working paper for the C11 standard: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf


Thank you kind sir, you win the prize for most coherent and informative technical snippet in the world. On this day anyway.


Accessing uninitialised memory is undefined. As in Nasal Demon undefined. If you don't zero out the padding, I'm sure there's a clever way to access those bytes in ways that invoke undefined behaviour.


The padding has unspecified values, which is distinct from being uninitialised.

If it were otherwise, you couldn't `memcpy()` structures around.


I believe there's an exception for the likes of `memcpy()`. Something along the lines of "type punning and reading indeterminate values is undefined except when we're reading through a `char*` or something.

I'll check the unbelievably thick book that tries to specify C11 (I've printed it, it's over 2 pounds).


The only way to access the padding without otherwise falling into undefined behaviour is by using a char * anyway (including indirectly using a char *, through memcpy()).


You say that as if it’s entirely the responsibility of the programmer to avoid these bear traps that have been left lying around everywhere.

Why not just have the compiler zero the memory, and thereby remove the trap? Seems very sensible to me. Do you think it’s a bad idea, and if so, why?


There is a concern for performance. But that's no reason. Zero initing could be default behavior that can be declared away. E.g.

As a type qualifier keyword:

  { int x, y; /* x and y are zero */ }

  { int noinit x, y; /* x is indeterminate, y is zero */ }
Or as a declaration specifier:

  { noinit x, y; /* both x, y indeterminately-valued */ }
Or a special constant for suppressing zero initialization:

  { int x, y = noinit; /* x zero, y indeterminate */ }
Similarly, unspecified order of evaluation could be supported by explicit request:

  decl (unspec_order) { /* comma-separated list of decl items */
     a[i] = i++; /* UB */
  }

  a[i] = i++; /* well-defined */


zero initing is default behavior for static values or structs.

    static int x, y; /* x and y are zero */


Good idea!


> You say that as if it’s entirely the responsibility of the programmer to avoid these bear traps that have been left lying around everywhere.

Oh no no no, I was picking on hermitdev's characterisation of the behaviour. Sure, what the compiler does with the padding bytes is unspecified. But it can still lead to undefined behaviour, if some unwary user ever reads them. A misinterpretation like that, and poof you get a security vulnerability. The C standard is insane.


Aha, sorry, I misunderstood! Glad to hear you’re on the side of sanity. :)


It's more than a logical or performance issue, it's a cultural one. In C culture, there's a sense that the programmer has direct control over the hardware. They can literally write or read to any memory address as they see fit, and have very fine-grained control over what the machine is doing.

Modern processors, with their out-of-order execution, complex caching algorithms, deep pipeliens and multi-threaded hardware often render this sense of control more illusory than factual, but the C culture remains wedded to the idea that the programmer is in control.

Accordingly, it's pretty provocative to suggest that a compiler or runtime would zero out memory without you specifically saying so. Any C programmer can overload malloc (doesn't zero memory) to calloc (which does). Whether it's a good or bad idea to do so is up to the programmer. The overall idea is don't do anything unless I say so.


Sane compilers should do that. The standard should eventually specify that. But before it does, you can not write portable code that expect that (but hopefully once enough compilers are sane but before the standard is updated, you can write code that targets only the compilers, and don't give a fuck about the other broken garbage that try to trap the world)


if you reference a null pointer then this behavior is 'undefined' from the perspective of the C compiler - however it is very well defined by the operating system (if you are doing a user space application).

No nukes get involved here - only core dumps.


If you are working on top of an operating system that launches nukes upon null pointer access, then you should consider to switch vendors.


> and document the behavior it will follow.

So it's unspecified in terms of the standard, but specified by the implementation


Right! Basically it's up to the compiler programmer to pick a path and follow it... assuming you're talking about implementation-defined.


The problem with this kind of approach is over time it removes the ability to use any other implementation. You are no longer using C, you are using <Implementation>C.

This becomes a problem when a different implementation adds amazing tools for finding bugs (the sanitizer suite, for instance), and you can't use them because your code doesn't build with any other implementation.


Large and complex pieces of software, and operating systems in particular, tend to be tightly tied to their compilers. It is never easy and in some cases practically impossible to port to a different compiler. I expect that Microsoft has come to terms with the fact that Windows will only support being compiled by their compiler.

When a different toolchain introduces a new feature for finding bugs that would be useful for Windows, the Microsoft compiler team can add that functionality to their own tools instead of porting Windows. An advantage of this is that they can customize the feature for exactly their use case. Yes, this is the definition of NIH syndrome, but that’s how large companies work.


Large pieces of sw have been able to switch some plateform specific code to other compilers (chrome for windows comes to mind).

This is probably way smaller than the whole Windows, but I would not be surprised if some MS dev are already internally compiling some of their components with clang for their own dev/testing (even if just for extra warnings, etc.)

And a major part of the work of the MSVC team today seems to be about standard compliance.

But yes, I do not really expect that they switch, and actually they probably don't even have the beginning of a serious reason to do so. This is not even a case of NIH. Their compiler derives from an ancient codebase and has been continuously maintained for several decades. They "invented" it. The only modern serious competition (that cares enough about Windows compat and some of their specific techs) has been started way after... They probably also have all kind of patents and whatnot about some security mitigations that are implemented by collaboration between the generated code and (the most modern versions of) low level parts of the Windows platform.


> . You are no longer using C, you are using <Implementation>C.

If you go deep and gnarly enough with your system, this is always the case, I'm afraid. There's a famous talk at Stanford by a Coverity... founder? consultant? about this.


> You are no longer using C, you are using <Implementation>C.

This is always the case because the C standard is only a partial spec. There's no such thing as "a program written in C(++)", there's only "a program written in <Implementation> C(++)". If you compile your program with a different implementation, then it's a different program. It may work, but it may not.

What I'd really like to see is a modified version of the C/C++ standards which keeps the language the same "in spirit" but removes all undefined and implementation-dependent behaviour. This would give compiler writers a stationary (or at least slower-moving) target to aim for and make it possible for C to be portable in theory as well as (sorta) in practice.


However in this case 'Standard C' is broken and <Implementation C> is not. The proper thing is to fix the standard to require padding bytes be zero'd.


It's easy to see both sides here. The overwhelming majority of code is not written to be run a in a kernel at the kernel-user security boundary, so for most code paying something to initialize padding might not be a great tradeoff. That is, the vast majority of code is running within a single security domain and doesn't need to protect itself from itself.

Still, avoiding initializing padding is probably not a great example of a performance win through standards exploitation: in the example given it's not clear why you'd not just do one 8 byte zeroing write to cover the whole structure, rather than apparently splitting it into a 4-byte and a 1-byte write. Perhaps this was 32-bit code, where 8-byte write are slightly trickier, but even two 4-byte writes are likely to perform just as well or better. Probably it's just bad codegen to treat the initialization of the struct[11] in two parts: a single struct and a 10-member array.


Luckily clang does a good job at being GCC compatible, so I don't worry too much about using GCC extensions. It's quite unlikely one of them will go away anytime soon, and theory pretty much cover all architectures/platforms that have ever existed.


Usually true, unless you want to target embedded, mainframes or some industrial OSes.


It doesn't support everything; for example, Clang doesn't do nested functions.


This was pretty much how writting C code between K&R, ANSI C89 and subsets e.g. Small-C used to look like.


I fail to see how implementing an unspecified part of the standard in a way which _doesn't_ leak kernel memory could ever be a problem.


It's not a problem for the compiler, of course.

The problem is the C code that relies on it: effectively you are using a dialect of C which gives stronger guarantees, so you lose the ability to use any other implementation which doesn't provide those guarantees.


Yeah, I (somehow...) missed the part where the GP explained that the kernel dev's fix was to just rely on the now updated unspecified behavior. I assumed the changed the compiler, but he also memset the structure before sending.


>The problem is the C code that relies on it: effectively you are using a dialect of C which gives stronger guarantees, so you lose the ability to use any other implementation which doesn't provide those guarantees.

How do you lose it in this case? You shouldn't been reading values from those padding bits anyway...


Tell that to a hacker. The problem here isn't that the code is functionally dependent on padding bytes, it's that when you copy those padding bytes around you are leaking information that you probably never meant to copy.

This can be problematic if you are copying kernel space memory to a user space process, for example. Let's say there's a call into the kernel that returns a copy of this 4+1 struct with three more bytes of padding. Maybe what was on the stack before the space was assigned to those last padding bytes are some information the kernel definitely shouldn't leak to user space, like some bytes of a password, and now any user space process could potentially read them simply by calling some unrelated kernel function.


It’s great that the compiler team could implement safer behaviour. But if the programmers’ intent was to zero all bits in the array they should express this explicitly in the code with a memset(). Otherwise a change in the compiler later could throw up this vulnerability again. The code should express the semantics as clearly as possible.


Then other other language lawyers will come around and tell you why you should use {0} instead of memset (e.g. because for some combinations of type and architecture the zero value isn't full of zero bytes).

This example also shows how "the semantics" is a fiddly concept. The reason the standard allows leaving bytes unzeroed is because they are not "semantically" important. But they actually do matter.

The problem with the mentality that it's always the programmer fault for not following "the rules" is they you eventually get to the point where the rules allow for no good solutions at all.


I didn't say it was always the programmers' fault. But I believe the programmer should express their intent as clearly as possible. And memset( (void*)buf, 0, buflen ) says fill-a-contiguous-array-of-unsigned-chars-of-value-zero, which is semantically different from initializing an array of structs that may have padding, and better matches the programmers' intent. It doesn't matter if the zero value is all 0 bits or not - the important thing is that the whole contiguous memory region is zeroed.

I believe C99 says chars and unsigned chars have no padding.

https://stackoverflow.com/questions/13929462/can-the-unsigne...


Another, better, response to your argument. Initializing an array of structs with = {0} does NOT tell the compiler that zeroing the entire contiguous chunk of memory matters - only that each struct should be zeroed. While memset( (void*)buf, 0, len) does tell the compiler that the entire contiguous memory chunk must be zeroed, which is what is intended.

Language lawyers need not apply.


It may be the right thing for the moment, but what happens to that code when new versions of the compiler come out? Someday it'll start leaking information again. Relying on non-standard behavior always ends in tears.


>Relying on non-standard behavior always ends in tears.

Who's relying on unspecified behavior? Do you mean some theoretical programmer? Well of course that's not a good thing, but I don't see what it has to do with the situation in the story and the MS engineers decideing to change how they implement that unspecified part of the spec.


The kernel programmer did, in this story.

An example of such an information leak is:

  struct foo {
    int a;
    char b;
  }

  void send_foo_01() {
    foo x {0, 1};
    write(fd, &x, sizeof(foo));
  }
which sends 3 bytes of the contents of the stack memory over the network, for almost every compiler except the one in the story. Running in a kernel, that could contain secrets.


Sorry, my mistake; yes, the kernel dev is now relying on the compiler to zero out those three bytes. I understand the decision to change this in the compiler, but I think the "fix" would have been to memset in the kernel code. I'd be surprised if they didn't do that, but maybe they can reasonably assume they'll never use another compiler to build the Windows kernel.


Signed integer overflow. It’s undefined because some platforms don’t use two’s complement.

Checking it after the fact is non-portable.


But not in sane compilers, they are better than the standard.

gcc, clang, icc all assume two's complement and happily overflow via -fwrapv. There's no such compiler on the Unisys anymore. They rather emulate two's complement. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2218.htm


Thankfully, not for very much longer...

http://wg21.link/P0907r2

C++, but apparently something similar is being considered for C as well.

https://twitter.com/jfbastien/status/989242576598327296?lang...


Isn't that mostly theoretical? I can't seem to find any processor that doesn't use 2's complement.


There are some old architectures that used one's complemeny and there are probably some still in service e.g.

https://en.m.wikipedia.org/wiki/UNIVAC_1100/2200_series


I had the pleasure of programming on these. Having both positive and negative zeros is special and that they don't compare equal is extra special. And yet -- ones complement arithmetic is not even the oddest thing about Univac 1100s. I think the Univac corporate values statement must have included both "Dare to be different" and "Remember your past".


Is anybody writing code for them? Probably not porting modern C anyway.

I assert this 'it might not be two's-complement' excuse is nonsense.


I seriously doubt it.

I do agree with you, it's not a big deal for most devs. The only place I'd worry about it is systems where it might be expected to be in service for many years or intended to be ported frequently. In that case, you never know what sort of crazy architecture you may end up with in the future.

There's always something a bit icky with not sticking to the spec, but in the grand scheme of things relying on two's complement is not a big deal.


from the proposal http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2218.htm

"Nowadays Unisys emulates their old architecture using x86 CPUs with attached FPGAs for customers who have legacy applications which they’ve been unable to migrate. These applications are unlikely to be well served by modern C++, signed integers are the least of their problem. Post-modern C++ should focus on serving its existing users well, and incoming users should be blissfully unaware of integer esoterica."


Presumably the compiler team wrote a test for that behavior so there won’t be a regression. I assume that Windows isn’t planning on switching compilers, so they can rely on that behavior as long as the Microsoft compiler passes all its tests.


Well, MSVC team is the last one who can propose something since they didn't even support C11 completely today, and weren't able to add C99 support for almost two decades.


They still don't support C99 fully.


They do, to the extent required by ANSI C++14, ANSI C++17 upgraded the requirements to C11.

They are pretty open the future of systems programming on Windows is C++ and .NET Native.

For C devs, they have helped clang to work on Windows and there is WSL for UNIX like software.

Just like they have improved Visual Studio integration with clang and gcc.

As for Visual C++, the name says it all.


Now that Microsoft is having again a new found love in C, either via Checked C research, the UDMF rewrite in C, WSL, or the upcoming Azure Sphere product, it would be interesting if they could contribute to improving the whole security story in C2X.


I don't think they are really that much in love with C aside from a few niche areas. The compiler itself still generates worse code when in C mode as it only exists for back-compat. When I worked there it was explicitly said that the new "universal" (or whatever they are called now) APIs were explicitly not targeting C. C++ on the other hand seemed to be undergoing a new renaissance. They have added some newer C features but only those required by the C++ standard.


Quite true, when speaking about Visual C++ and I have also stated the same thing multiple times here.

Their C love on the projects I mentioned, is via clang and gcc.


> Problem solved.

This "solution" also prevents code analysis tools from detecting reads from padding bytes as "non-initialized memory reads".

When a routine leaves sensitive data on the stack, the entire area used up by that sensitive data, must be wiped out before the routine returns (and still, wiping out padding bytes would not be required). How about the part of the stack space not covered by that array of 11 elements?


The kernel has a separate stack, inaccessible to user-space.

Otherwise, you'd be right: a shared stack would be a giant source of information leakage from kernel space to user-space unless it was very carefully managed (probably at a significant performance cost). Thus, separate stacks (it also has the advantage of not needing to make assumptions about how user-mode programs use their stack, e.g., if they are transiently using "unallocated" stack above rsp, etc).

Probably what happened here is that this structure was copied back to user space (e.g., as the result of a system call) exposing the kernel data.


At Sun Solaris and Studio were quite separated organizationally (and business-wise too). Mind you, the Solaris engineering group had early access to Studio and also, of course, access to the Studio team, so... not quite joined at the hip, but not too separated either.


In C11, the spec was changed to make zeroing out padding mandatory.


> This UB was leading to disclosure of little bits of kernel memory back into user mode because Windows engineers assumed that = { 0 } was the same as leaving the variable uninitialized and then memsetting the whole thing to zero

But what on earth were they doing with the padding bits?


They aren't doing anything with the padding bytes. But what probably happened was they copied the array into userland memory. Which potentially allows a malicious sandboxed program to read the padding bytes that contain bits of kernal memory.


Total guess, but they could have been including them in a hash function or struct equality check (equality with memcmp, hash by just grabbing bytes, etc.).

That would not have gone well with uninitialized padding :-)


It's not uncommon for a function to use a supplied output buffer as scratch space. So the padding could have contained pretty much anything.


I'm skeptical that it was implemented that way because of kernel memory leaking concerns.

More likely it was done to prevent Windows API calls from panicking when they accessed unset parameter structures.

As a former Windows programmer, that was one of the largest sources of errors back in the Win32 days.


But you don't access the padding; it's generally implicitly added by the compiler to comply with the ABI rules for the platform. That argument might make sense if this was about zeroing _all_ stack objects not explicitly initialised, but it's explicitly talking about the padding.


> This UB was leading to disclosure of little bits of kernel memory back into user mode

If you write inline assembler, you can access this stuff anyway. So I'm not seeing what the value is in zeroing it by the caller. The kernel callee should zero its stack frame before returning.


How so? The kernel presumably has a separate stack which is not accessible to user-space, but here information was disclosed because a structure copied back to user space was create on the stack, initialized to {0} and then member-wise assigned, with some padding bytes never being touched and thus containing whatever previous values happened to be on the kernel stack. So far this is all in kernel-space so nothing been exposed yet.

Then, however, if this structure is copied back to user-space, e.g,. as an output parameter of a kernel call, the padding bytes with the exposed data will be copied along with it (unless you get lucky and the copy routine happens to make the exact same decision with regard to padding handling).

If the kernel stack _itself_ was visible to user-space, you'd have a whole separate set of problems: you'd have to zero the whole stack (or at least the extent of the stack that could have been touched) on every kernel call.


Yes, you're right.


There may be an expectation at work for you to have the desire to advance within the organization, i.e. career ambition.


It says 8.6 on the page


dsr_ followed the column down a bit off and got the Feb 2017 seasonally adjusted number (they are one column apart) - they should really separate those better


Just finished benchmarking this for a key workload in our build process. It's 3% faster than Node 8.x for us. But node-chakracore (the Microsoft runtime) 8.9.4 was 11% faster -- we are considering switching to that.


Assuming you're testing on Windows, node-chakracore is currently released as a beta, so Node 10 is probably the more appropriate comparison.


Is that really worth it, though? What's the support like for chakracore?


it's a build process. it should be fine.


Can you share more details on this build workload? Like what does it do? what packages it uses ? etc.


Can you even measure 3% accurately and repeatedly?


Such a weird title; it makes me think he works for them, but he doesn't



didn't he work for microsoft previously?



Man, I really wouldn't. My understanding is that of the people who present to the emergency department with chest pain, something like a third of them have been using cocaine. It causes Real Problems.

https://www.drugabuse.gov/publications/drugfacts/drug-relate...


Manchego on the other hand, worth every penny and a great source of butyrate, https://www.researchgate.net/publication/304454916_The_neuro...


This is a little disingenuous, without further elucidation. As far as the statistic you have quoted is concerned, it tells us nothing about how dangerous cocaine is. We need to know how many out of the total population of cocaine users experience chest pain, how many of them go to an ER, and then how many of those (who in total make up 1/3 of ER presentations with chest pain) are further diagnosed with some actual serious problem...

if we don't know what the outcome of these ER visits are, then it could well be that for some tiny percentage of cocaine users there is a side effect that causes the perception of chest pain, which disappears with no ill effects after a few hours. or, maybe, this represents almost all cocaine users - 90% of them experience severe enough chest pain to warrant an ER visit, all of whom are pronounced dead withing minutes of arrival.

annoyingly, the website you linked to which details this singular datum, does nothing to clarify as to what the truth of the matter is. it certainly doesn't appear to be "advancing addiction science" in any useful way...


That could also mean a third of the population uses cocaine.


thanks for the link. I need to find updated stats on that. I wonder if the number of those in the ER because of cocaine has risen....


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: