01:53 | <shu> | ljharb: you've been vocal in the past about coercing arguments in the order in which they appear. is there code that you've seen that actually depends on that ordering? |
01:53 | <shu> | i'm thinking of proposing a breaking change to the order of coercion for Atomics methods like Atomics.store(ta, idx, val) to coerce idx, val, then validate the TA |
01:54 | <shu> | with resizable buffers, having to recheck detached/out-of-boundness and reloading the length after each argument coercion is really unfortunate |
01:55 | <shu> | it's kind of a bugfarm (sometimes security bugs) |
02:31 | <ljharb> | no code i think the committee would respect, I’d guess. why is it a bug farm? |
02:31 | <ljharb> | I’m confused about the problem it’d be solving |
02:35 | <Jack Works> | Agree with shu. Don't think coerce order will break anything |
02:45 | <shu> | it's a bug farm because it's easy to forget that coercing idx and val can detach ta |
02:45 | <shu> | (and with resizable buffers, can resize ta ) |
02:46 | <shu> | TA detachment and resizing is a qualitatively worse kind of user code than other arbitrary user code, because code that forget to recheck for detachedness after each argument coercion can end up reading out-of-bounds into the buffer, depending on the implementation |
02:46 | <Jack Works> | "easy to forget" do you mean when v8 is optimizing code? |
02:46 | <shu> | that, and i also mean engineers or spec authors actually forgetting even when implementing the slow path |
02:46 | <shu> | i personally missed a bunch of these in the resizable buffers spec draft |
02:48 | <shu> | TA and Atomics methods depend on the TA being in a valid state, life will just be a lot easier if we can rework these methods to 1) validate once instead of multiple times and 2) after validation, check that no user code can ever be called again until method exit |
02:50 | <shu> | I’m confused about the problem it’d be solving |
02:51 | <shu> | to be clear, user code re-entrancy is a general problem. i'm singling out TAs because TA bugs result in more, and more serious, security bugs |
02:54 | <Jack Works> | So the ideal order is: idx check, val check, (no user code now), TA check, Atomics.store, (user code again)? |
02:54 | <shu> | it's a little trickier than that unfortunately, because val coercion depends on looking at whether ta is a BigInt TA or a non-BigInt TA |
02:55 | <shu> | so i think the ideal order is: coerce but not validate left-to-right, then validate left-to-right |
02:55 | <Jack Works> | lgtm |
02:55 | <shu> | so the order is: 1) ensure ta has the right internal slots, 2) coerce idx , 3) coerce val , (no user code after this point) 4) validate ta , 5) validate idx (if needed for atomic access) |
03:45 | <ljharb> | in general, does anything validate besides TAs and Proxy? |
06:50 | <Richard Gibson> | ljharb: I think that depends upon your definition of "validate". For example, there are six opportunities for String.prototype.split to throw an exception (and also observably checks arguments out-of-order)—does that count? |
14:52 | <ljharb> | im trying to understand she’s mental model here; it’s probably fine if TA/Proxy is “special” but i still don’t understand why it’s not easier to implement correctly if you fully process args left to right |
15:02 | <Ashley Claymore> | because processing later args can invalidate previous validations |
15:30 | <shu> | ljharb: yeah what Ashley Claymore said. fully left-to-right means you validate ta , then validate idx , then validate val , then need to validate ta again |
15:31 | <ljharb> | ahhhhh ok |
15:32 | <shu> | cause of, you know, valueOf and whatnot |
15:32 | <ljharb> | thanks, that makes sense now, let me think about it |
15:33 | <shu> | actually in the resizable case it's even dumber |
15:33 | <shu> | it's validate ta , validate idx , validate val , re-validate ta , then also re-validate idx because ta might not be out of bounds but just shrunk a little bit |
15:34 | <Ashley Claymore> | while (somethingCouldChange) validateArgs(...args) |
16:32 | <yulia> | rbuckton: just checking, did you see my invite for today? |
16:33 | <rbuckton> | I did not, no. |
19:34 | <ljharb> | shu: so, generally i think of "processing" arguments left to right - not necessarily validating them. meaning, i'd maybe expect something like:
thoughts on that? |
19:53 | <shu> | yes that seems to match what i said above about an "ideal order" |
19:53 | <shu> | coerce left-to-right, then validate left-to-right |
19:53 | <shu> | where "coerce" is the phase that can call user code |
19:53 | <shu> | right now we don't have such a distinction, and we do both at the same time |
19:58 | <ljharb> | right. my earlier question is because i suspect most things don't actually need to "validate" (or at least, don't need to validate something that could be changed by user code post-coercion), so it doesn't come up often |
20:00 | <shu> | yeah |
20:01 | <shu> | so it sounds like you're amenable to having distinct phases like that? |
20:01 | <shu> | (if web compatible, of course) |
20:03 | <ljharb> | tentatively yes, i'd just want to make sure there's no weird cases that would arise from applying that rule universally (which might be fine ofc, but it's hard to know in advance) |
20:11 | <shu> | i wasn't planning on applying it universally |
20:12 | <shu> | though i suspect you are right that basically only TAs (and DataViews) and proxies even have a sense of "valid state" at all |
20:12 | <shu> | but i only really care about TAs and DataViews |