I have a javascript object defined inside a string variable:
const str = "{a:1}";
I wonder what is the best way to convert it to a javascript object. I have searched a lot but all I found is to use JSON.parse or JSON.stringify to convert the string. But the tricky part in this string is that it is not a JSON object. The a is not quoted. I have tried below approach but it doesn't parse it to a object:
JSON.parse(JSON.stringify(str))
I know I can parse the string manually but I am looking for a more generic solution which support parsing all possible javascript object string.
var obj = eval(str);
Just be aware that using eval can have performance and security impacts.
If you don't control the content of str, i.e. it is a user input or it comes from a server you don't trust, the are risks.
Also, the JavaScript runtimes optimizes your code at runtime, but often disable many optimizations when engineering an eval.
Try to wrap the evaluation statement in a self invoked function that receive the variable passed to theeval:
(function(s) {
return eval(s);
}(str));
It ensures the creation of a closure to isolate the eval, mitigating it's potential impacts.
And last, don't take anything I've just said as an absolute truth: benchmark your code with and without the eval, just to be sure.
Related
I will reference to Mozilla's docs about String object.
JavaScript automatically converts primitives to String objects, so that it's possible to use String object methods for primitive strings. In contexts where a method is to be invoked on a primitive string or a property lookup occurs, JavaScript will automatically wrap the string primitive and call the method or perform the property lookup.
Good example of such situation would be accessing length property:
let word = "Hello";
word.length;
I have understood that what happens in this situation is:
let word = "Hello";
String(word).length;
But after trying some benchmarks it's clear for me that word.length is much faster than String(word).length. It seems that implicit conversion is something completely different than String(word), much faster. I cannot find any info about how this implicit conversion works, but it might be helpful to know in some optimization problems.
The reason for that is probably time to parse and the fact that inner JS string object (that is actually C++) works faster then creating extra interface to interact with string on high JS level...
So it's all about optimisation
There is good article about it (https://dev.to/promhize/what-you-need-to-know-about-javascripts-implicit-coercion-e23).
I have a json file where i am rendering the template and have an object like
"templateLabelEval":"return $row->['document_code'];"
I am rendering the label by using
eval(templateLabelEval);
Is there any other alternative way where i could avoid using eval as it is considered to be a bad practice
Given that the code string has a return statement, eval alone wouldn't work anyway, but you could use Function().
var result = Function(data.templateLabelEval)();
This has nearly all the same security concerns, but not so much the performance issues that eval has (or had). So of course, you should only execute code that is secure.
To explain the code, passing the string to the Function constructor creates a new function object with that strings as its body. (I assume the function needs no parameters defined for now.) So the trailing () invokes the function immediately and the result is stored in result.
You could store the function itself if you want, and then invoke it later as many times as you'd like.
I have a json data that has unknown objects like this:
var x = {
"unknown1": 234,
"unknown2": 324
}
I can get the properties name as:
var prop1 = Object.keys(x)[0];
Now I want to find the value of this property. I can obviously do x[prop1], but I wanted to do x.prop1. My question is:
What are ways to convert prop1 into an expression so that I could use x.prop1?
If eval can solve this then how and why would eval create security problems in this case?
What are ways to convert prop1 into an expression so that I could use x.prop1?
You can't, without generating source code and compiling/evaluating it.
If eval can solve this then how and why would eval create security problems in this case?
Yes, eval (and its close cousin new Function) can do this. It's only a security issue if what you're evaling comes from an untrusted source. If you can trust that the value of prop1 doesn't contain malicious content, then you can use eval("x." + prop1) to do this. Or new Function("x", "return x." + prop1)(x).
But there's no good reason to. Just use x[prop1]. That's what brackets notation is for. It's normal practice, it doesn't have to fire up a parser and code generator, it's faster, and you don't have to worry about prop1 having malicious code in it. If you use eval or new Function, it's not normal practice, it has to fire up a parser and code generator, it's slower, and you have that niggling concern in the back of your mind. So use x[prop1]. :-)
As #mhodges says in his comment you could add a new property.
but it might seem redundant to do so.
x.prop1 = x[Object.keys(x)[0]]
I'm seeing code in the following form - is such use of eval() safe?
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset=eval("document."+frm_name);
var x=eval("document."+frm_name+".edit_key");
var y=eval("document."+frm_name+".cAction")
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
Its used as:
<a href="javaScript:;" onClick="genericTakeAction('frmSearch',
'<?php echo $rec_id;?>','<?php echo $pagenum?>','makeOpen')"
class='link6'>Make Open</a>
Whether it's right or wrong, it's needlessly complicated.
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset = document[frm_name];
var x = rset.edit_key;
var y = rset.cAction;
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
This works because in JavaScript, you can access an object's properties in one of two ways: Either using dotted syntax and a literal identifier, e.g. x = obj.foo;, or using bracket syntax and a string identifier, e.g. x = obj["foo"];. (Note how foo was not in quotes in the first one, but was in quotes for the second; but both do exactly the same thing. Also note that since the property name is a string in the second case, you can use any expression that results in a string, so y = "f"; x = obj[y + "oo"]; also works.)
P.S. It's wrong
eval() is generally frowned upon because, as you are already aware, it is considered unsafe.
In the browser environment, however, it is less of an issue, because in fact, any user could eval() any code they wanted to, using tools like Firebug, etc.
There is still an issue, in that the eval() embedded in the code can be run without the user knowing that he was triggering an eval(), but it's still much less of an issue than in a server-side environment like PHP.
eval() is actually typically used as you've shown to run JSON code being returned from a server-side request. Newer browsers can import JSON more safely using a dedicated JSON parse() function, but older browsers do not have this function and are forced to use eval() for this. Most JSON libraries have eval() in their code somewhere for this reason, but will generally do some sanitisation of the input before running it through eval().
Even if it might look a little bit convoluted, as others have already mentioned, from a pure security perspective, you have to make sure that the 'frm_name' parameter of the genericTakeAction() function can never contain user-supplied data.
In your example, the 'frm_name' parameter contains the hard-coded literal 'frmSearch'. So it is ok as long as this genericTakeAction() function does not get called somewhere else with user-supplied data for the 'frm_name' parameter.
See http://en.wikipedia.org/wiki/Cross-site_scripting#Traditional_versus_DOM-based_vulnerabilities
Here is the problem string:
$.ajax(......
,success:function(msg){
var obj = eval('['+msg.d+']');
},
....
}
msg.d contains something like:
new Person(2, 'Name Surname','This is just string came from Par'is at Sat'urday');
How can pass the javascript problem ?
If the string really is as you've quoted it, it has a syntax error and will not work (it has an errant ' inside the word "Saturday"). Otherwise, though, change the brackets ([ and ]) in your eval call to parentheses (( and )):
var obj = eval('('+msg.d+')');
However, it should almost never actually be necessary to do this (or indeed to use eval at all). It's almost always possible, and desirable, to refactor slightly and avoid it.
If that's a literal quote from your code, see also dvhh's answer below, your function argument name (msg.d) is invalid.
Using eval in this scenario is actual quite dangerous. You really ought to be using XML or JSON. (That's why they call it AJAX.)
the function argument should be a valid javascript identifier
try changing msg.d to msg_d for example
You may need to escape your string, because this example works fine:
function MyObject(myvar){
this.hello = function(){
alert('myvar= ' + myvar);
};
}
var obj1 = new MyObject('hello');
obj1.hello();
var obj2 = eval("new MyObject('world')");
obj2.hello();
(Edit: By the way, I assume msg.d is a typo due to editing the snipplet before posting on StackOverflow ?)
I would avoid using eval() for security reasons. If a user can get malicious code into the database, there's a chance it could end up in this eval expression, wreaking havoc for anybody who visits this page.
Instead of using eval, I'd recommending returning JSON from the AJAX request. You can then easily parse the values and build a new Person object with that data.