I am trying to create buffer in a .js file, and then passing that buffer to a c++ addon where I will call a Windows API.
In the c++ addon I have:
auto buf = node::Buffer::Data(args[0]);
auto len = node::Buffer::Length(args[0]);
Are there any guarantees that node::Buffers are null-terminated? Or does node::Buffer::Length have any other form of safety check to prevent an overrun?
No. Think of buffers as a minimal data structure containing length and memory; they are not raw memory like what malloc() provides. A buffer is protected against memory overruns within a JavaScript context but not if you pass a pointer to the buffer memory to C/C++. And because a Buffer can be used to store binary data (as well as a string) it doesn't provide an extra byte to null-terminate a string; it doesn't "know" what is in the buffer.
I don't think the code you've posted will work; This post does a good job of explaining how to use buffers in C/C++: https://community.risingstack.com/using-buffers-node-js-c-plus-plus/
Related
I'm using the Windows credentials store like this:
PCREDENTIAL cred = nullptr;
if (CredRead(entryName, 1, 0, &cred) != TRUE || !cred)
return -1;
// ... code which handles cred.UserName and cred.CredentialBlob
CredFree(cred);
As you can see I free the buffer as required. However, I see that the LPBYTE pointer CredentialBlob is still valid an still contains the password in memory. Do I have to SecureZeroMemory it manually and who owns the buffer? I found no other source code which does that...
I haven't found anything, https://msdn.microsoft.com/library/aa919793.aspx contains just the following generic statement:
Clear credential data from memory after use
Do not leave credentials in memory after use. Clear all credential data from temporary storage after use by calling SecureZeroMemory.
You own the buffer. The documentation states:
Any pointers contained within the buffer are pointers to locations within this single allocated block.
In an ideal world, CredFree would zero the entire block before freeing it, and it might be worth submitting a suggestion to Microsoft to this effect, but as things stand, your best bet is probably to do the following before calling CredFree:
SecureZeroMemory (cred->CredentialBlob, cred->CredentialBlobSize);
However, I see that the LPBYTE pointer CredentialBlob is still valid
How do you determine this? Most likely you are committing UB by reading dead memory.
an still contains the password in memory
This is more concerning but the text you quoted tells you what to do about it.
I have no problems implementing the memory mapped file. The question is. Assuming this returns a valid memory view.
void* pBuf = MapViewOfFile(hMapFile,
FILE_MAP_WRITE,
0,
0,
0);
Do i have alternatives to using memcpy to give data to it? for instance can i tell my application to store data in it? I really want something like char* buffer = new char[1073741824] where the new places the data in the memory mapped file. this seems logical. or will i have to write a wrapper that writes to the memory view using memcpy? that would be disapointing.
Probably the easiest approach is to use the boost memory mapped file classes which give the additional benefit of being portable.
You can use the placement new operator or you can cast the address to a structure or class you want to use. The advantage of placement new is that the constructor of the class will be called. If you use from then on that pointer you don't need to copy the data but read and write directly to it.
I create a byte array in java and pass it by reference to the jni function. This I do in a loop and and sometimes get a out of memory error in the jni. I wanted to know if java automatically frees the array on every iteration or since it is passed to the jni function, it doesn't ??
JNI Code (bOldArray is the java byte array that i pass to jni as an argument)
len = (*env)->GetArrayLength(env,bOldArray);
char *oldBuff = (char *)calloc(sizeof(char),MAX_SIZE);
jbyte* bytes = (*env)->GetByteArrayElements(env,bOldArray,0);
memcpy(oldBuff,bytes,len);
(*env)->ReleaseByteArrayElements(env,bOldArray,(jbyte *)bytes,0);
you have 2 buffers here, one handed from your java code (bOldArray)and the local buffer (oldbuff) which you allocated in line 2.
in fact, you might have more buffers, because
(*env)->GetArrayLength
with almost certainly makes a unmovable copy of the memory (needed for c-pointer-access), which holds the array in you java code and with
(*env)->ReleaseByteArrayElements(env,bOldArray,(jbyte *)bytes,0);
this memory is copied back onto the memory of your java array (check documentation of the last argument of ReleaseByteArrayElements)
but about you problem: you should free oldBuff too.
free(oldBuff);
else the VM does free your c-copy of the java array but not the self-allocated part directly (it might do thiz later due to object-lifetime and garbage collection, but this is unpredictable and therefore the out-of-memory error is also unpredictable)
to avoid the java-c-copy mechanism (speeds up performance) use a shared/static buffer like ByteBuffer
If you are using GetByteArrayElements you have to call ReleaseByteArrayElements after you are done with the array in JNI, because the JVM will prevent the freeing of this array in java until you do so.
Please post the code to get a clearer idea
I have programed an application on windows XP and in Visual Studio with c++ language.
In that app I used LoadResource() API to load a resource for giving a file in the resource memory.
It returned a pointer of memory block and I wanna cast the pointer to the std stream to use for compatibility.
Could anyone help me?
You can't cast the resource to a stream type. Either you copy the bytes:
std::stringstream ss;
ss.rdbuf().sputn(buf, len);
or you wrap your resource in your own streambuf:
class resourcebuf : public std::streambuf {
// Todo: implement members including at least xsgetn, uflow and underflow
};
and pass it to istream::istream
Why would you need this?
Casting raw data pointers to streams means byte-by-byte copying of your resource and, therefore, lacks in performance (and, also to mention, I don't see any benefit in this approach).
If you want to work with raw memory, work with it. Casting here (compatibility?) seems to be a very strange approach.
Still, if you want to do it, you could create some stream from your memory block, that treats it as a sequence of bytes. In this case, it means using std::stringstream (istringstream).
After you lock your resource by LockResource, create a string from received void* pointer and pass it to your stringstream instance.
void* memory = LockResource(...);
// You would probably want to use SizeofResource() here
size_t memory_size = ... ;
std::string casted_memory(static_cast<char*>(memory), memory_size);
std::istringstream stream(casted_memory);
Most straightforward way is probably to convert the buffer to string and then stringstream:
std::stringstream ss(std::string(buf,len));
I think that will copy it twice, though, so if it turns out to be taking a lot of time you might need to look for alternatives. You could use strstream, but it might freak out the squares.
Hokay so I have an application where I need some IPC... I'm thinking named pipes are the way to go because they are so easy to use.
Anyways, I have a question about how to handle dynamic memory using named pipes.
Say I have a class such as this:
class MyTestClass {
public:
MyTestClass() { _data = new int(4); }
int GetData() { return *_data; }
int GetData2() { return _data2; }
private:
int* _data;
int _data2;
};
Now when I create a buffer full of MyTestClass objects then send them over the pipe, I'm obviously losing _data in the destination process and getting garbage. Is there some strategy to this that I should use? I can use value types for simple cases, but for many complex classes I need to use some sort of dynamic memory and I like pointers.
Or, should I just look at using shared memory instead? Thanks
Both named pipes and shared memory have similar issues: You need to serialize the contents of the structure into the on the sending side and deserialize the structure from the on the receiving side.
The serialization process is essentially identical whether you're using named pipes or shared memory. For embedded pointers (like _data and _data2) you need to serialize the contents of the pointer in a consistent fashion.
There are lots of serialization strategies that you could use, depending on how your structures are laid out in memory and how efficient your IPC has to be. Or you could use DCE RPC and let the RPC marshaling code handle the complexities for you.
To send the data over a named pipe, you must serialize (or marshal) the data on the sending end, and deserialize (or unmarshal) it on the receiving end.
It sounds suspiciously as if you are simply writing a copy of the bytes in the data structure. This is no good whatsoever. You aren't copying the allocated data (it isn't stored between the first and last bytes of the data structure, but somewhere else altogether) and you are copying a pointer (_data) from one machine (or process) to another, and the memory address in the local process has no guaranteed meaning in the other.
Define yourself a wire protocol (if desparate, look at ASN.1 - no, on second thoughts, don't get that desparate) that defines the layout of the data for transmission over the wire. Then implement sender and receiver (or seralizer and deserializer) functions. Or find someone else's code that does this already.
Also remember to deal with endian-ness - you must define which sequence the bytes are sent through the named pipe.
For example, you could define that the message sent consists of a 4-byte unsigned integer in network byte order defining how many structures follow, and each structure could be a sequence of 4 signed 4-byte integers for the array followed by a single signed 4-byte integer for _data2 (also sent in network byte order).
Note that the choice of named pipe as the IPC mechanism is largely immaterial; unless you are using shared memory (inherently on the same machine), then endian-ness has to be dealt with, and even with shared memory, you need to deal with serialization.