I'm attempting to iterate a string but seem to be getting a weird access violation, The problem is caused when passing a value returned from JSON.stringify because the data seems to be read only, upon many attempts to use hacky methods to solve the issue I have not been successful in doing so.
I've tried copying the data, manually iterating the string and copying the string over to another variable, but the issue still remains the same no matter what I've tried.
The code below works flawlessly when a protected piece of data is not passed
xor_swap(keys, data)
{
for(var i = 0; i < data.length; i++)
data[i] ^= this.xor_key_exchange(keys, i);
return data.toString('utf8');
}
How ever when applying a parameter (for instance JSON.stringify), The data becomes protected and no matter what I seem to do the data seems to not be modifiable.
var enc = this.xor_swap(keys,JSON.stringify(data));
Please note that the input is completely correct, I have tested this many times.
Of-course the expected output is that the string should be iteratable, and after speaking to a few people who are very experienced in nodejs they can't seem to see why this problem is being caused.
I am not using strict-mode for anyone asking.
Thanks to anyone who can help me with this problem
In Javascript string is immutable. You cannot do the following
var a = 'hello';
a[1] = 'a' // try change 'e' to 'a', not possible
console.log(a)
JSON.stringify() returns a string which by definition is immutable.
So, this assignment here is invalid
data[i] ^= this.xor_key_exchange(keys, i);
thanks for your reply, I noticed that the conversion to a string is indeed immutable.
So I ended up solving this problem by simply converting the string to a buffer, completing my xor and then just converting the buffer directly back to a utf8 string again.
xor_swap(keys, data)
{
var buf = Buffer.from(data);
for(var i = 0; i < buf.length; i++)
buf[i] ^= Math.abs(this.xor_key_exchange(keys, i));
return buf.toString('utf8');
}
Thank you very much for your help
Related
Code:
m_cbReminderInterval.ResetContent();
for (int i = 1; i <= m_iMaxReminderInterval; i++)
{
COMBOBOXEXITEM cmbItem = {};
CString strNumber;
strNumber.Format(_T("%d"), i);
cmbItem.mask = CBEIF_TEXT;
cmbItem.iItem = static_cast<INT_PTR>(i) - 1;
cmbItem.pszText = strNumber.GetBuffer(_MAX_PATH);
strNumber.ReleaseBuffer(); // TODO: When should I release the buffer - NOW or AFTER the InsertItem call?
m_cbReminderInterval.InsertItem(&cmbItem);
}
My question is:
Is it better to use GetString instead of GetBuffer in this context? The only issue I see is that pszText is LPWSTR whereas GetString returns LPCWSTR. If I should continue to use GetBuffer then when should it actually be released? Before or after the InsertItem call?
There's a common pattern in the Windows API you'll see over and over again: Structures that are less const-correct than what would appear to be possible. Undoubtedly, some of them are oversights, but not this one: COMBOBOXEXITEM is used both to insert and query an item's data.
This is hinted to, in part, in the documentation for the pszText member:
A pointer to a character buffer that contains or receives the item's text. If text information is being retrieved, this member must be set to the address of a character buffer that will receive the text.
The second part of the contract is omitted from the documentation, sadly. When setting an item's text, the control makes a copy of the string passed in, and neither takes ownership over the pointed to data, nor modifies it. In other words: When using the COMBOBOXEXITEM structure to insert an item, all pointers can be assumed to point to const.
Following that, it is perfectly valid to pass the pointer received from GetString():
for (int i = 1; i <= m_iMaxReminderInterval; i++)
{
COMBOBOXEXITEM cmbItem = {};
CString strNumber;
strNumber.Format(_T("%d"), i);
cmbItem.mask = CBEIF_TEXT;
cmbItem.iItem = static_cast<INT_PTR>(i) - 1;
cmbItem.pszText = const_cast<TCHAR*>(strNumber.GetString());
m_cbReminderInterval.InsertItem(&cmbItem);
}
According to CSimpleStringT::GetBuffer:
If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before you use any other CSimpleStringT member methods.
You are not modifying the string, so you don't need to call ReleaseBuffer.
But as you said, it's better to use GetString, at least you indicate your intent to NOT modify it.
I was implementing the little Java class to solve the string problem on Hackerrank:
Given the string, find its non-reducible form, considering one valid operation is to delete any pair of adjacent letters with same value.
Ex:
"aabcc" would become either "aab" or "bcc" after 1 operation.
However, I just want to mention about the block of code surrounding this error. Although I was able to solve the problem quite fine, I'm tempted by others to improve the solution's time performance by using the better approach of StringBuilder()
But I haven't figured out why the behavior of append() in my StringBuilder class could lead to the memory overflow or any sort of more complicated misbehavior.
Here's the code:
static String super_reduced_string(String s){
StringBuilder res = new StringBuilder();
for (int i = 1; i < s.length(); i++){
if (s.charAt(i-1) == s.charAt(i)){
/* waste so much memory leak!!! java.lang.OutOfMemoryError: Java heap space
//s = res.append(s.substring(0, i-1)).append(s.substring(i+1)).toString();
*/
s = s.substring(0, i-1) + s.substring(i+1);
i = 0;
}
}
//then check if it's non-empty, print it out
if (s.length() != 0){
return s;
}
return "Empty String";
}
The part where I commented out is the misbehavior mentioned above. Please kindly help me reason through this bug, and debug it! It shouldn't be that hard.
Just clear string builder after assigning to s.
s = res.append(s.substring(0, i-1)).append(s.substring(i+1)).toString();
res.setLength(0);
Part of a program I was working with needed to append string values to a vector. I reached a segmentation fault when appended the string values like so:
for(int i = 0; i < testvec.size(); i++) {
testvec[i] = oldvec[i];
}
But my program compiled and executed correctly with this code:
for(int i = 0; i < testvec.size(); i++) {
testvec.push_back(i);
}
This is the gist of it, what we were doing was updating a vector
push_back() is the correct way to append items to a vector. It will reallocate the underlaying memory block as needed to fit the new items. operator[] however, does not grow the vector, so it can only insert new items if the vector was previously resized with resize() or by inserting with push_back(). If you try to use operator[] without doing so, it will result in undefined behavior.
operator[] indexes into already existing space in a vector. Say your vector was default constructed:
std::vector<std::string> v;
Then doing v[i] for any i is undefined behaviour, as there is no guarantee that any space has yet been allocated to store values. It's effectively equivalent to:
std::string *storage;
storage[i] = "...";
Your code still looks incorrect: I'm guessing it's actually something like:
for(int i = 0; i < oldvec.size(); i++) {
testvec.push_back(oldvec[i]);
}
This is the long way of going about it: to construct a vector that has the elements contained in another vector, the simplest way is:
std::vector<std::string> testvec(oldvec.begin(), oldvec.end());
I know parts of this issue is covered by some posts here and I have looked at them and tested some but with no luck.
I have this native method signature which should populate the provided CBadgeData structure array with results:
int elc_GetBadges(int nHandle, char* cErr, int* nRecCount, CBadgeData** arr)
The CBadgeData structure is implemented as follows:
package test.elcprog;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
public class CBadgeData extends Structure{
public static class ByReference extends CBadgeData implements Structure.ByReference { }
public int nBadgeID, nTrigger, nExtraData;
public String cName;
public CBadgeData(Pointer pointer){
super(pointer);
}
public CBadgeData(){ }
public String ToString() {
return nBadgeID + "," + nTrigger + "," + nExtraData + "," + cName;
}
#Override
protected List getFieldOrder() {
String[] s = new String[]{"nBadgeID","nTrigger","nExtraData","cName"};
return Arrays.asList(s);
}
}
My last try to craft this argument and call the method looked like this:
CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items];
new CBadgeData.ByReference().toArray(badges);
int ret = inst.elc_GetBadges(handle, err, recCount, badges);
It fails with segmentation error.
My Question is what Java type should be provided here as an argument for the native CBadgeData** in the call to elc_GetBadges?
EDIT -1-
Populating the array myself (with or without terminating null pointer) didn't work and caused further Seg crashes. I then used Pointer[] arg as technomage suggested:
Pointer[] pointers = new Pointer[max_items];
for(int i=0; i<max_items; i++){
pointers[i] = new CBadgeData.ByReference().getPointer();
}
int ret = inst.elc_GetBadges(handle, err, recCount, pointers);
This caused no error but seems to not make any changes to the returning struct which should have contain 4 items in this case:
int bid = new CBadgeData(pointers[i]).nBadgeID; // this returns null for all items
Using explicit read() / write() on the struct led to Seg crashes again (on the read):
Any idea what am I still missing here?
EDIT -2-
Interestingly enough - using the Memory.get directly, after calling the native method, gets the correct results:
Memory m= (Memory)pointers[0];
System.out.println("1st int: "+m.getInt(0)); // this gets 24289 which is 5ee1
System.out.println("2nd int: "+m.getInt(4)); // this gets 3
System.out.println("3rd int: "+m.getInt(8)); // this gets 255
System.out.println("String: "+m.getString(12)); // this gets "Badge[5EE1]" as supposed
But the read() still crashes. Any thoughts?
I'm inferring that CBadgeData** input is intended to be an array of pointer to CBadgeData.
As such, the Structure.ByReference tagging is correct.
Structure.toArray() is probably not appropriate here, or at least not necessary (it allocates a contiguous block of structs in memory). You can just populate your array with CBadgeData.ByReference instances.
Perhaps your callee is expecting a NULL pointer at the end of the array? I don't see another indicator of the array length to the callee.
CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items+1];
for (int i=0;i < badges.length-1;i++) {
badges[i] = new CBadgeData.ByReference();
}
badges[badges.length-1] = null;
Pretty sure that works. If for whatever reason there's a bug handling Structure.ByReference[], I know that Pointer[] is reliable and will do the same thing.
EDIT
If you use Pointer[] instead of Structure.ByReference[] (please post a bug to the project site if Structure.ByReference[] does not work), you will have to manually call Structure.write/read before/after your native function call, since JNA will not know that the pointers reference structures that need to be synched with native memory. I'd bet, however, that the cause of your crashes when using Structure.ByReference[] was simply that JNA was automatically calling Structure.read() after the call and triggered the same error that you see when calling it explicitly.
If you get a segfault on read, it likely means that your structure fields aren't properly aligned or defined, or (less likely) that you have corrupt data that can't be read properly. To diagnose this, set jna.dump_memory=true and print out your struct after calling Structure.write() to see if the contents of the structure appear as you'd expect. It'd also help to post the native and JNA forms of your structure here, if possible.
have a look at the code below once and help me out by clarifying my doubts.
I have commented my doubts on each lines where i have doubts. Moreover, its a part of code from a huge one. so please ignore the variable declarations and all.
The whole code is working perfect and no errors while compiled.
double Graph::Dijkstra( path_t& path )
{
int* paths = new int[_size];
double min = dijkstra(paths); // **is a function call or not? bcz i didn't found any function in the code**
if(min < 0) { delete[] paths; return -1;}
int i = _size - 1;
while(i>=0)
{
path.push(i); // **when will the program come out of this while loop, i'm wondering how does it breaks?**
i=paths[i];
}
path.push(0);
delete[] paths;
return min;
}
Full coding is available here.
double min = dijkstra(paths); // **is a function call or not? bcz i didn't found any function in the code**
It almost certainly is. However, it could be a free function, member function, function invoked by a macro, or something else. Without seeing the rest of the code, we can only guess.
while(i>=0)
{
path.push(i); // **when will the program come out of this while loop, i'm wondering how does it breaks?**
i=paths[i];
}
The program will come out of the loop as a soon as i is less than zero. If I had to guess, I'd say the each node in the path contains a link to the previous node's index with the last node in a path returning -1 or some other negative number.