-
Notifications
You must be signed in to change notification settings - Fork 66
Buffer.from/Buffer.alloc/Buffer.allocUnsafe/Buffer() soft-deprecate #7
Conversation
### Buffer.alloc(size[, fill]) | ||
|
||
Allocates a new initialized buffer of `size` bytes. If `fill` is specified | ||
and is a string, the Buffer is allocated off the shared pool by calling: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and is a string
I would expect it to work as Buffer(size).fill(fill)
does, in all cases (everything else is implementation details), except for the cases where .fill()
doesn't work (e.g. .fill('')
doesn't fill).
For example, I would expect Buffer.alloc(2, 10)
to give the same result as Buffer(2).fill(10)
— <Buffer 0a 0a>
.
Also, is Buffer.alloc(1e8)
really allocated from the pool?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, is Buffer.alloc(1e8) really allocated from the pool?
Allocations are of size Buffer.poolSize >> 1
or smaller. So it could, depending on what the user sets poolSize
to. But by default no.
@jasnell Since we're here, may want to add Buffer.alloc(size[, fill[, encoding]])
so the encoding of the string can be specified. I should have done this on initial implementation but didn't think about it then.
Also, if alloc()
is used then I suggest we also don't use a pool. Since other Buffer's contents can be accessed via buffer.buffer
it might be considered a security violation, and the whole point of this thing is to not do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trevnorris ... +1 SGTM
On Jan 25, 2016 4:27 PM, "Trevor Norris" notifications@github.com wrote:
In XXX-buffer-alloc-from.md
#7 (comment):
+* Soft-Deprecate the existing
Buffer()
constructors and introduce new
Buffer.from()
,Buffer.alloc()
andBuffer.allocUnsafe()
factory methods- to address Buffer API usability and security concerns.
+* Add--zero-fill-buffers
command line option to node to force all Buffers- to zero-fill when created
+## Details
+
+The details of the proposal are captured by [Pull Request 4682][] in the
+nodejs/node repository (https://github.com/jasnell/node/tree/buffer-safe).
+
+### Buffer.alloc(size[, fill])
+
+Allocates a new initialized buffer ofsize
bytes. Iffill
is specified
+and is a string, the Buffer is allocated off the shared pool by calling:Also, is Buffer.alloc(1e8) really allocated from the pool?
Allocations are of size Buffer.poolSize >> 1 or smaller. So it could,
depending on what the user sets poolSize to. But by default no.@jasnell https://github.com/jasnell Since we're here, may want to add Buffer.alloc(size[,
fill[, encoding]]) so the encoding of the string can be specified. I
should have done this on initial implementation but didn't think about it
then.Also, if alloc() is used then I suggest we also don't use a pool. Since
other Buffer's contents can be accessed via buffer.buffer it might be
considered a security violation, and the whole point of this thing is to
not do that.—
Reply to this email directly or view it on GitHub
https://github.com/nodejs/node-eps/pull/7/files#r50779681.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But by default no.
I made a mistype, was talking about Buffer.alloc(1e8, 'a')
. If that's not allocated off the shared pool, then the text here should be changed:
If
fill
is specified and is a string, the Buffer is allocated off the shared pool by calling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sigh... yep, I keep forgetting the little nuances there of what is pooled vs. what isn't. I'll get the docs updated properly in the next round :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trevnorris ... buf.fill()
does not currently accept an encoding
argument does it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasnell it doesn't. i'm working on that patch right now to fix the API hole.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just want to echo @ChALkeR's point that buf.fill(val)
currently accepts number values and this API should do that too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, the proposal PR has been updated to account for that. For
completeness, @trevnorris and I are also working on allowing both fill()
and alloc(size, fill)
to accept a Buffer
and to accept an encoding
when a string is passed in, e.g:
// these are silly examples, but you should get the idea:
Buffer.alloc(10, 'foo', 'ascii');
Buffer.alloc(10, Buffer.from('foo'));
Buffer.alloc(10).fill('foo', 'ascii');
Buffer.alloc(10).fill(Buffer.from('foo'));
+1 on this, but the text should be clarified, details are a bit off. |
|
||
``` | ||
Buffer.allocUnsafe(size).fill(fill); | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect. Instead a simple call to new Uint8Array()
, without setting the kNoZeroFill
flag, and simply setting the prototype of the uint8array to Buffer.prototype
, using Object.setPrototypeOf()
.
EDIT: nm. read this out of context. the above simply states the allocation mechanics. which is also stated below.
@jasnell Thanks much for working on this. Nice to see a simple EPS that's to the point. |
I still object to the word "unsafe" here ("safe" as well) but if I'm the only one left pushing this barrow I won't hold up progress with it. |
I'm also still against the word "unsafe". Either call the functions according to what they do without subjective assessments, or just don't provide the non-zero-filling version at all. |
@seishun That's pretty much what it does, as @joepie91 noted here: #4 (comment), #4 (comment), and all over that thread. Also, from my point of view the technical aspect doesn't really matter that much — what matters is how that would affect the ecosystem security, and explicitly marking at a |
/cc @evilpacket, @feross, @mafintosh. |
@ChALkeR Accept that there are those who disagree that Unsafe is a proper technical description. Comments like:
are fundamentally opinion of a developer's aptitude and don't have technical merit. I've agreed to proceed with using Unsafe, despite the fact agree with @rvagg and @seishun that it's an incorrect description of the operation, because it shouldn't be holding up the API document as a whole. Maybe I'll fight it more once the document gets closer to completion, but in the mean time want to proceed with getting real work done. |
At this point re: the naming, the focus needs to be primarily on refining the actual changes and documentation as opposed to bikeshedding on the name. I don't think we're going to identify a single name that will make everyone happy so at some point we're going to need a compromise on it. |
Apologies if I've missed this discussion from another thread, but what's the rationale for accepting an optional fill value to This seems clearer and simpler: Buffer.alloc(5).fill('hello') than this: Buffer.alloc(5, 'hello') And it keeps the API surface area a bit smaller and simpler. Is there some kind of optimization we can do at the C++ level if we know the fill string? |
I'm working on seeing if we can optimize it down to a single step. We may not be able to or it may not be worth the trouble -- in which case we should likely not accept the fill on the alloc. It's there currently to facilitate experimentation. |
@feross That API would require a double-fill. if users don't care about the performance implications then that's fine, but the decision was made around preventing as much impact as possible. I highly doubt there's a magical way I haven't heard of to do operation look-ahead and know the user is following up the |
@trevnorris My concern is the API is more complicated than it needs to be. What I don't like in the current proposal is that Buffer.alloc(size, [fill], [encoding])
Buffer.allocUnsafe(size) If we eliminate the extra arguments to Buffer.allocUnsafe(size).fill(fill) If users don't care about the performance implications, they can do: Buffer.alloc(size).fill(fill) |
Of course, if there's some way to optimize an alloc + non-zero fill value into one step, then that's a good argument for keeping the additional arguments. But if it's just calling |
@feross ... i'm starting to lean that way but I have a couple of ideas of optimizing that I want to try out first. Hopefully I'll be getting to those this week. |
@jasnell Nice - thanks for the update. |
@feross Even if the operation is completely performed at the C++ level, it will essentially be no more than a |
@feross @trevnorris ... OK, here's the current breakdown:
While In general, most developers will typically end up using |
The asymmetry also serves the purpose of highlighting that they are quite different operations with different implications. We can even explain why the same arguments are not supported in the non-filled version. |
One additional difference that I just implemented in |
@jasnell The asymmetry makes sense to me now.
Wow. |
@feross .. yep, I just discovered that a couple weeks ago myself ;-). |
Slight correction ... |
@jasnell I found that out only a week ago (#7 (comment)), and that looks like a bug to me, actually. I would say that the correct behavior on |
calling |
I certainly don't disagree with that, but I'll submit a separate PR to fix
|
Unfortunate that the EP couldn't serve its purpose of hashing out the API. C'est la vie. |
Add the Buffer.from/alloc/allocUnsafe EPS (correctly this time, I hope)