Hacker Timesnew | past | comments | ask | show | jobs | submit | simiones's commentslogin

> Array memory is on the stack.

Array memory can sit on either the stack or the heap.

> The size of that array is actually not known at run time, its only known at compile time, where any reference to that length gets resolved by the compiled.

This is also a bit misleading, in two ways. First, it's not clear what you mean by "size" here - the size of the memory block(s), or the shape of the array?

Second, many people think that the C runtime doesn't know the amount of memory allocated to an array, but this is actually false. It's just the C abstract model that for some reason chose to not expose this information - but the size is actually always stored and accessible, and this is virtually mandated by the standard: otherwise, `free(arr)` couldn't realistically work, it would have to be `free(arr, size)`. This is one of the weirdest inefficiencies of C, in fact - it requires you to store the size of arrays twice - once in user code, and another time in the internal logic of the allocator.

Edit: and as a fun extra, C++ not only inherited this mistake from C, but reproduced it again, meaning that a C++ array allocated with new[] actually stores the size twice, at least with typical implementations - once in the C++ runtime and again in the allocator - and still requires the user-space code to store it a third time. This is because `delete[]` needs to call the destructors of all of the elements of the array, regardless of where and how the array was allocated, so the number of array elements needs to be stored alongside the object itself.


>Array memory can sit on either the stack or the heap.

No, if we are using the definition of an array that is like int c[] = ..., that is always going to be on the stack. Heap continuous memory =/= array. You can use the [] operator to access it like an array, but fundamentally, as far as structures in C language are concerned, those 2 are different, because they get treated by compiler differently.

>but the size is actually always stored and accessible, and this is virtually mandated by the standard: otherwise, `free(arr)` couldn't realistically work,

That would only be true if each element in the array was a char.

The dynamic data structure stores total amount of memory allocated by address, it has no info about the size of the element, so it can't infer the actual number of items at runtime. You could write your own malloc that does this, but generally, that is left to the user for flexibility. For example, a really good practice in C coding that basically solves any double free is a mempool that allocates all the memory up front. That way, you never really even have to call free, and the memory you allocate can be partitioned any way you chose dynamically.


> that is always going to be on the stack.

Unless your C implementation doesn't use a stack for data storage. Which existed, you know: IIRC the C compilers for Cray machines used linked lists to hold activation frames. And of course, there are PIC microcontrollers where you can't really use the hardware stack for anything except return addresses.


> int c[] = ..., that is always going to be on the stack

Why? In the following code, only c will be allocated on the stack:

  int a[]={1,2,3};
  foo() {
    static int b[]={1,2,3};
    int c[]={1,2,3};
  }

The point is anything that is not dynamically allocated has size known at compile time.

> No, if we are using the definition of an array that is like int c[] = ..., that is always going to be on the stack. Heap continuous memory =/= array. You can use the [] operator to access it like an array, but fundamentally, as far as structures in C language are concerned, those 2 are different, because they get treated by compiler differently.

Well, not necessarily. For one thing, if we have a function foo(int c[]), it's debatable if c is an array variable or a pointer variable. However, what's not debatable is that you can allocate a struct on the heap, and that struct can have an array member - e.g. `struct foo { int a[10]; }; [...] struct foo *x = malloc(sizeof(struct foo));` would allocate an array on the heap as part of the struct.

> That would only be true if each element in the array was a char.

That's why I said that it depends on what exactly you mean by the size of the array. It's also true that in today's world at least, malloc() will often allocate more memory than you actually ask for, to optimize against fragmentation - and then the internally stored size is the size of the actual allocation, not the logical size that you requested - which may not even fit into a whole number of array elements. So, I was being a little overly simplistic (lying) for dramatic effect.

> For example, a really good practice in C coding that basically solves any double free is a mempool that allocates all the memory up front.

While this is a very valid technique for certain purposes, especially when dynamic allocation is needed in very high performance code, it's very much not a valid solution for memory safety - quite the contrary, it's a terrible practice for that. In particular, this is almost exactly the issue that caused the infamous HeartBleed vulnerability in OpenSSL to stay hidden for so long: the use of a memory pool for the buffers used to store TLS packets was hiding the buffer overflow from UBSan and valgrind and similar tools, since the reads were perfectly valid from a language perspective (they were never reading from free()d/unallocated memory, only from memory that had been released to the memory pool).


Its all about what the compiler sees.

Structs are a defined type, which means its construction (and therefore total size) has to be known , the array definition with size is necessarily part of that struct type. So anytime that struct is used, the compiler needs to see its definition, and thus can safely infer the size. Thats pretty much the whole reason structs are a thing - the very basic type that allows you to pass around data format during the compilation process.

Arrays are not defined as types in C, they are really at most just syntax convenience. So if another function takes an array as a parameter, and it gets compiled as part of a file, there is no way for the compiler to auto infer what would get passed into it.

Char allocation usually involves +1 bytes for null terminated strings, which is used as a signal for allocated memory. So strlen(char *) is accurate.

>quite the contrary, it's a terrible practice for that. In particular, this is almost exactly the issue that caused the infamous HeartBleed vulnerability in OpenSSL to stay hidden for so long: the use of a memory pool for the buffers used to store TLS packets

The heartbleed vulnerability was not due to mempool. It was due to a combination of lack of bounds checking, and not zeroing out the memory containing secure keys when its deallocated. Even if it didn't use mempool, leaks would still be possible.


> Second, many people think that the C runtime doesn't know the amount of memory allocated to an array, but this is actually false. It's just the C abstract model that for some reason chose to not expose this information.

There are some counterpoints:

1) Conceptually, allocated memory block and data structure / array in it are not related. You can allocate memory block and then subdivide it to multiple different structures / arrays. You can implement sub-allocators.

2) Heap allocator does not need to store exact length of allocated object. For example, it could have several fixed-length slab allocators for smaller objects, select matching one during malloc() and use address range to find slab during free().

3) Array can be also on the stack (VLA or alloca()).

4) Arrays can be also on memory allocated outside of C library allocator (e.g. mmap()).


All are fair points, I was being a bit cavalier with the facts. I'll also add that many if not all modern malloc() implementations actually allocate somewhat larger amounts of memory than your request, to respect various alignment requirements and/or to avoid excessive fragmentation - even when not using pure slab allocations.

I do think the C++ bookkeeping from new[]/delete[] however has few if any similar caveats - the runtime really needs exactly the kind of information you also need in your code; the only caveat I can imagine is that it might omit this information for types that don't need destruction, such as `int`, but I don't know if this is a plausible optimization in realistic use cases that are not trivial.


In C, a[i][j] can mean either a[i,j] or a[i][j], depending on the type of a.

> As AI becomes capable of producing entire work products, the profession that has spent decades treating “I reviewed it myself” as the standard of care has no framework for what happens when that review becomes economically irrational. The ethical rules assume a human at the center. The technology is moving humans to the periphery.

What horrendous morals behind this article. Why would anyone advocate for prioritizing economics and technology before ethics, especially in something as important as law?

The "won't someone think of the all the poor people with no access to legal counsel" part sounds a lot worse once you realize they actually mean "won't someone think of the money we're leaving on the table by not getting some revenue from selling cheaper AI slop, uh I mean AI legal representation, to those who can't afford anything else".


This sounds reasonable, but it doesn't seem to reflect reality. The biggest reason that shows are region locked and/or removed from streaming sites are licensing deals, not technical reasons. Movie and TV production companies are the ones pushing for the region locks, and the ones selling limited distribution rights to streaming services.

So, while you are right that video streaming is much more costly than audio streaming, I think GP is overall more correct about the reasoning being production costs rather than anything to do with distribution.


There's nothing really special about VSCode here, except that it's really popular. You could just as easily attack Emacs or Vim or Sublime or [...] users by distributing a malicious extension.

You can’t attack them that easily because of the different publication method. Emacs, Vim, and Sublime have a pull model (like linux distros), not a push model. Meaning you add your repos to the package hub, you do not upload an archive to them. The Hub will pull in you changes (or the plugin manager will do so). The only way in is to take over the repo itself.

Not sure how Vim and Sublime work, but for Emacs, publishing to MELPA is absolutely a push process, where you open a PR to MELPA's repo with a recipe for your new package; and, once it's accepted, every commit to your repo results in a new package build on MELPA's servers that Emacs users will get when they update / install the new plugin.

It’s not. The developer never build a package and then upload on melpa. Melpa will fetch the needed files and build the package. It’s not truly secure, but an attacker would need to publish a new commit and wait for quite some time for people to update.

Another thing is that some packages are old. Seeing an update out of the blue would be very strange. And for packages that are updated more often, I guess the maintainer would be quite surprised to see a new commit they’ve not approved of.


My point is, if I want to create a malicious Emacs plugin, I can do the following:

1. Create a new Emacs package, create a PR to register my GitHub repo as a new package in MELPA's repo, and wait for them to accept the PR. Ideally the plugin should be benign at this point.

2. Wait for people to pick up this new extension, while it's still benign.

3. Push the malicious version to my own GitHub repo. MELPA will automatically pick it up, build it, and package it.

4. Anyone updating their Emacs packages from MELPA or installing it from MELPA will pick up this malicious version.

Now, this does require that the malicious code is visible on the extension's GitHub page; I'm not sure if this would be true on VSCode as well.


> 2. Wait for people to pick up this new extension, while it's still benign

Good luck on that. Check the most popular packages and they all belong to fairly well known people in the community. If it’s something small, people usually just copy the relevant bit to their config. And rarely do huge systems pick up users without active advocacy (helm, ivy, vertico, company, magit, consult, hyperbole, emms, org-mode,…) which means collaboration and plenty of people looking at upstream.


Sure, but this is just an accident of Emacs being a much more niche product, not related in any way to the design of the package system. If Emacs suddenly gained VSCode's popularity, I can assure you that numerous new users would simply look through MELPA and pick up packages that sound useful, and quickly end up picking up malware - nothing in Emacs prevents this any more than VSCode.

> I can assure you that numerous new users would simply look through MELPA and pick up packages that sound useful, and quickly end up picking up malware

But the issue is not new users picking up unconfirmed packages. It’s about active employees getting compromised by extensions they trusted. As the nature of packages update is opaque and the default settings leave you vulnerable.

If you go on magit’s page on melpa, you get the commit id used for the build and if you wanted too, you could diff the files with upstream. Everything is transparent. Meanwhile what you got on marketplace is whatever is pushed by a token.

And another nice thing about packaging system like emacs is that they rely on peer dependencies instead of pulling their own from the internet. Which is nice, because when a bug is patched, you update that single dependency and you’re done. No need to update every package that depends on it.

[0]: https://melpa.org/#/magit


Transparent doesn't mean secure. The very source of this issue was a recent NPM supply-chain attack, and you can also check the sources of any NPM package that you use. NPM also relies on peer dependencies, and this is exactly why malware spreads so efficiently in the ecosystem - just like it helps spread bug fixes, it also helps spread malware as efficiently.

Very, very few people, even in tech circles, check the sources of all of their dependencies. Sure, compromising magit's sources will be hard - but you don't need to compromise magit. Just compromise one of magit's dependencies and watch the malware spread.

Edit: in fact, you don't even need to compromise Magit's dependencies. Since the developers of Magit probably use Emacs themselves, you can probably just compromise some small Emacs package that happens to be used by someone on the Magit team, get access to their repo from there, and then you actually may be able to compromise Magit itself (depending on how strict their code review etc rules are).


I do think you mean sex, not gender - trees don't really have a gender or gender expression. Either way, it would be rather irrelevant, as most trees planted in cities have both male and female flowers (oak, birch, most conifers), or even hermaphroditic flowers (citrus).

Great, now I have to hate trees for being gender-fluid, too?

I just spent $500 on gay conversion therapy for my dog! /s


Conversely, it may be that it's only labels in language that are unifying disparate parts into a single "neural system" concept. Ultimately the world is either individual particles and fields, or it is all Oneness, Brahman, and anything else is just arbitrary unification/division; but we can't know which is which.


> Any argument that a "soul" exists or that consciousness does not arise from the physical world (eg our neurons) is literally unfalsifiable.

This is an metaphysical discussion, so falsifiability is kind of irrelevant. All metaphysical positions are ultimately unfalsifiable - including materialism and physicalism just as much as dualism or monism or theism.


> All metaphysical positions are ultimately unfalsifiable

This is not true, there are many metaphysical positions that are falsifiable.

For example, "anything shaped like an apple is an apple" is a metaphysical position. It defines what it means to be apple-ish. You could hold that metaphysical position and also "apples are always made of plant material" as another position you hold at the same time.

Then you could falsify the metaphysical position by presenting a stone carved into the shape of an apple. You could choose to deny reality and change your physical definition (what the definition of the word "apple" is), but if you think logically the evidence constructively falsifies the original metaphysical position.

I think what you might have been trying to say is that people tend to adopt metaphysical positions which are non-falsifiable. Yes, they do, but that doesn't mean no metaphysical arguments can be resolved through logic and experiment.


True, I should have been more careful with my wording. My point was actually that unfalsifiable metaphysical statements are not invalid in the same way that unfalsifiable physical/scientific statements are.

So yes, some metaphysical statements are falsifiable, and some have in fact been falsified over time. And, very importantly, many of the biggest metaphysical questions have no known falsifiable answers (at least none that are not already known to be false, of course).


I don't think creationism is nonsensical, it's just wrong. But the concept overall is not nonsensical - in principle, if the universe were very different, a god could have molded humans out of clay and breathed life into them or whatever other fairy tale is preferred; it's not a logically inconsistent, so it's not nonsensical. Even something like Lamarckism is not nonsensical.

If you want to see an obviously nonsensical world view, you need to look at something like the Time Cube "theory". Rovelli is essentially claiming that dualism is more in this area - which I agree with the GP is quite unlikely for such a long discussed and influential philosophical idea.


This problem, while interesting in its own right, is entirely irrelevant to consciousness. Especially because, regardless of how it's achieved, it's actually very clearly known that we do have temporal processes in our body - our tell-tale hearts being quite an iconic example.


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

Search: