I have an idea for a game where people can type in some simple instructions for their character like player.goLeft() or player.attackInFront() and for that I have people type their code into a text box and then I parse it into eval(). This works well but it also allows people to change their own character object by typing things like player.health = Infinity; or something similar. I have a list of functions I want to allow people to use, but I am unsure how to restrict it to only use them.
I understand that the whole point of not letting people use eval is to avoid accidental cross-site scripting but I am unsure on how else to do this. If you have a suggestion please leave a comment about that.
I asked some people around on what to do and most suggested somehow changing scope(which is something I was not able to figure out) or to add some odd parameter to each function in my code that would be required to be a specific string to execute any function, but that seems hacky and since I am making the game in browser with p5js it would be easy to just inspect element and see what the password is.
basically every character has variable called "instruction" which is just a string of javascript. Then every frame of the game I execute it by doing eval(playerList[i].instruction);
tl;dr, how can I only allow specific function to be executed and not allow any others?
EDIT: I forgot to mention that I also am planning to provide player with information so that people can made code that would adapt to the situation. For example there will be parameter called vision that has vision.front and vision.left etc. These variables would just say if there is an enemy, wall, flower, etc around them in a grid. Some people suggested that I just replace some functions with key words but then it compromises the idea of using if statements and making it act differently.
EDIT 2: Sorry for lack of code in this post, but because of the way I am making it, half of the logic is written on server side and half of it works on client side. It will be a little large and to be completely honest I am not sure how readable my code is, still so far I am getting great help and I am very thankful for it. Thank you to everybody who is answering
Do NOT use eval() to execute arbitrary user input as code! There's no way to allow your code to run a function but prevent eval() from doing the same.
Instead, what you should do is make a map of commands the player can use, mapping them to functions. That way, you run the function based on the map lookup, but if it's not in the map, it can't be run. You can even allow arguments by splitting the string at spaces and spreading the array over the function parameters. Something like this:
const instructions = {
goLeft: player.goLeft.bind(player),
goRight: player.goRight.bind(player),
attackInFront: player.attackInFront.bind(player)
};
function processInstruction(instruction_string) {
const pieces = instruction_string.split(' ');
const command = pieces[0];
const args = pieces.slice(1);
if (instructions[command]) {
instructions[command](...args);
} else {
// Notify the user their command is not recognized.
}
};
With that, the player can enter things like goLeft 5 6 and it will call player.goLeft(5,6), but if they try to enter otherFunction 20 40 it will just say it's unrecognized, since otherFunction isn't in the map.
This issue sounds similar to the SQL Injection problem. I suggest you use a similar solution. Create an abstraction layer between the users input and your execution, similar to using parameters with stored procedures.
Let the users type keywords such as 'ATTACK FRONT', then pass that input to a function which parses the string, looks for keywords, then passes back 'player.attackInFront()' to be evaluated.
With this approach you simplify the syntax for the users, and limit the possible actions to those you allow.
I hope this isn't too vague. Good luck!
From your edit, it sounds like you're looking for an object-oriented approach to players. I'm not sure of your existing implementation needs, but it would look like this.
function Player() {
this.vision = {
left: '',
// and so on
}
}
Player.prototype.updateVisibilities = function() {
// to modify the values of this.visibility for each player
}
Player.prototype.moveLeft = function() {
}
Don't give the user an arbitrary interface (such as an input textfield that uses eval) to modify their attributes. Make a UI layer to control this logic. Things like buttons, inputs which explicitly run functions/methods that operate on the player. It shouldn't be up to the player as to what attributes they should have.
Related
I want to allow users to enter their own math formulas into a field that I can run via javascript, but I only want them to enter math related code and also let them have access to only the Math object.
So I only want the user to be able to enter math symbols (+, -, *, %, etc) and use any function in the Math object.
I initially thought about using regex on the client and server to verify that they are only typing in what i allowed, and since they wont be able to run that code before it goes to the server, i thought maybe it would be OK, but I still don't know if just regex itself would even work for this.
How can I go about safely allowing and trusting a users input like this?
Edit: The formulas will always run on the client, but I will store them in the db as a string that i can send to them when they want to run it.
So a number of comments led me to find MathJs, and from reading some of the docs and comments on that site I see it is safe to allow user input and also allows the Math object.
And combining this with workerpool to limit execution time, I think that should have everything I'm needing.
Thanks to those who helped point me in the right direction!
If you can guarantee that text will not be executed on the server then conceptually you can try evalFormula below :
<html>
<head>
<script type="text/javascript">
function evalFormula(str) {
// shielding
var window = null;
var document = null;
// shortcuts
var abs = Math.abs;
return eval(str);
}
console.log( evalFormula("abs(-42)") );
console.log( evalFormula("document.write('')") ); // throws error
</script>
</head>
<body>
</body>
</html>
Note that the function contains // shielding section that shall contain "caps" for all "dangerous" objects that shall be prohibited in formula context.
Note: that set is quite difficult to define in full but in principle possible.
Local scope of the function may contain shortcuts of Math functions, so they can be used as abs(-42) but not as Math.abs(-42).
Idea of the code above: In JS eval() gets executed in context of current function. So all its local variables are available for the text being evaluated.
I'm sort of building an AI for a Telegram Bot, and currently I'm trying to process the text and respond to the user almost like a human does.
For example;
"I want to register"
As a human we understand that the user wants to register.
So I'd process this text using javascript's indexOf to look for want and register
var user_text = message.text;
if (user_text.indexOf('want') >= 0) {
if (user_text.indexOf('register') >= 0) {
console.log('He wants to register?')
}
}
But what if the text contains not somewhere in the string? Of course I'd have like a zillion of conditions for a zillion of cases. It'd be tiring to write this kind of logic.
My question is — Is there any other elegant way to do this? I don't really know the keyword to Google this...
The concept you're looking for is natural language processing and is a very broad field. Full NLP is very intricate and complicated, with all kinds of issues.
I would suggest starting with a much simpler solution, by splitting your input into words. You can do that using the String.prototype.split method with some tweaks. Filter out tokens you don't care about and don't contribute to the command, like "the", "a", "an". Take the remaining tokens, look for negation ("not", "don't") and keywords. You may need to combine adjacent tokens, if you have some two-word commands.
That could look something like:
var user_text = message.text;
var tokens = user_text.split(' '); // split on spaces, very simple "word boundary"
tokens = tokens.map(function (token) {
return token.toLowerCase();
});
var remove = ['the', 'a', 'an'];
tokens = tokens.filter(function (token) {
return remove.indexOf(token) === -1; // if remove array does *not* contain token
});
if (tokens.indexOf('register') !== -1) {
// User wants to register
} else if (tokens.indexOf('enable') !== -1) {
if (tokens.indexOf('not') !== -1) {
// User does not want to enable
} else {
// User does want to enable
}
}
This is not a full solution: you will eventually want to run the string through a real tokenizer and potentially even a full parser, and may want to employ a rule engine to simplify the logic.
If you can restrict the inputs you need to understand (a limited number of sentence forms and nouns/verbs), you can probably just use a simple parser with a few rules to handle most commands. Enforcing a predictable sentence structure with articles removed will make your life much easier.
You could also take the example above and replace the filter with a whitelist (only include words that are known). That would leave you with a small set of known tokens, but introduces the potential to strip useful words and misinterpret the command, so you should confirm with the user before running anything.
If you really want to parse and understand sentences expressed in natural language, you should look into the topic of natural language processing. This is usually done with some kind of neural network trained to "understand" different variations of sentences (aka machine learning), because specifying all of different syntactic and semantic rules of the language appears to be an overwhelming task.
If however the amount of variations of these sentences is limited, then you could specify some rules in the form of commonly used word combinations, probably even regular expressions would do in the simplest case.
I've been writing C/C++/C# for decades, and have used JavaScript as needed for web projects, but want to expand that and do some more in-depth development with Canvas and JavaScript.
My concern is how easily you can make mistakes like setinterval() instead of setInterval(), for example. I'm using VisualStudio and have Telerik's JustCode plugin that does some static analysis, but there's so much that it doesn't check.
I also worry about calling object methods or properties that just don't exist. I understand why these things empower the language and developer with greater flexibility, but how do I best protect myself from the unintended consequences of that flexibility?
I struggled with JavaScript's dynamically-typed nature for a long time too. It turned out to be quite liberating when I finally made peace with it. Here's the mantra that has worked for me:
Program correctness is the most important thing. If I am confident my program exhibits the correct behavior, either my types are correct, or any existing typing errors don't effect program behavior.
This shift in thinking puts more of an emphasis on testing -- which is a good thing. If your tests are well-written, and comprehensive, then type errors will be caught.
I also tend to employ much more of a functional paradigm in my JavaScript coding: if you are not mutating state, strong typing has less meaning.
Of course if you really feel that strong typing is important, there is always TypeScript, which compiles directly to JavaScript and is, by all accounts, an excellent language.
Good design is the answer. Just because it's Javascript and it gives you a lot of freedom doesn't mean the principles you've used until now are any less valid. Design by interfaces (or even better, by contract), make class diagrams, put pen to paper, etc. Do be careful about Javascript's very own brand of object-orientedness, learn about it and the associated patterns (SO has many questions about them) and await ES6 Harmony eagerly.
If you want an IDE, or at least an environment, that tells you what's wrong in a readable and easy-to-use fashion, I recommend simply using your favorite browser's console (your fav browser should be FF or Chrome). Firefox + Firebug is particularly good though, and a favorite among many Web developers. The console, just like in Python, allows you to test snippets of code and to solve your naming errors very fast.
When I finished university I was a promising young lad and was sure that I will have no problems with finding some work. After a while... Bang! The World Economic Crisis struck. So I had to accept some cheap and ugly job and after I fed up with them, I started to search for something better and I risked everything. You might wonder why I am telling all this to you in a semi-scientific site. I am telling you, because through my story you will understand why I am answering the way I am answering. After 3 years of searching for my place and constantly training and educating myself I've got an offer from a small group of programmers, who were using some technologies which were very alien to me. I have joined them and I had to learn many things: .NET framework, Visual Basic, Javascript, jQuery, CSS, Telerik, a lot of libraries. I knew this was my chance to stabilize my position and I was a very trained learner (I have been constantly learning, but in different areas), so I have spent two weeks working 16 hours instead of 8 and at the end I was a constructive member of the team, still a bit rusty in the newly learned languages and technologies, but my results were quite decent. Shortly after that I became used to all the things used there and had no problems.
The thing is that I learned Javascript while learning a lot of other things as well and working in the meantime, having a tight schedule for the tasks. Just like you, I did not like Javascript has no types. I do not like it even now, after all those years. But I had no time to make it more comfortable to me and now I am so used to it that I am too lazy to create something which would help me and the thing would no longer help me.
If you do not want to get used to it the hard way, I believe something like this would help you:
function StrongType(weakValue) {
//int
this.i = function() {
return parseInt(weakValue);
};
//float
this.f = function() {
return parseFloat(weakValue);
};
//string
this.s = function() {
return weakValue + "";
};
//boolean
this.b = function() {
return !!weakValue;
};
//change
this.c = function(newValue) {
weakValue = newValue;
};
//natural
this.n = function() {
return weakValue;
};
}
This would help you to make sure you always know the type you are using. Function names:
You could create a strategy for yourself about how a name is typed and use that for all your functions and variables. If you are using some function and its name is not ok for you, then you can do something like this:
function MyNameHelpers() {
this.setTimeOut = function(callback, interval) {
return setTimeout(callback, interval);
};
}
Also, let's suppose you have a foo object and you want to use its bar member, possibly with parameters:
function MemberUser() {
this.useMember = function(owner, member, error, errorParams) {
if (!!owner) {
return owner[member];
} else {
//error is a function to handle the case when owner is falsy
return error(errorParams);
}
};
this.callMethod = function(owner, member, params, error, errorParams) {
if (!!owner) {
return owner[member](params);
} else {
//error is a function to handle the case when owner is falsy
return error(errorParams);
}
};
}
The codes above are just illustrations, I did not test/use them, maybe things are needed to be added and so on, but you get the idea. You will either get used to Javascript like I did, or create a library to prevent you from making mistakes. It is your choice.
i try to figure out a greasemonkey script that replaces every onmousedown on a site with an ondblclick. And i want it to constantly update, like every 1,5 Seconds, because the page refreshes using AJAX.
This is the script i came up with, but it doesn't seem to be working.
window.setInterval(document.body.innerHTML= document.body.innerHTML.replace('onmousedown','ondblclick');,1500);
The page it should work with is internal use only. But a good example would be the google search, where onmousedown is used for the links of the results to swap out the URL before you click it.
I also tried it without the semicolon after the document.body.innerHTML.replace.
I'm really new to JavaScript, but since i'm the only one in the company who can code, this one is stuck with me.
Any help would be appreciated.
Also, a small "side question"
Do i have to use #exclude, or is it enough to only use #include internal.companysite.tld* so it will only work on this site ?
A direct answer: you need to supply a function to setInterval - and it's best to set a variable so that you can later cancel it with clearInterval() if necessary.
function myF(){document.body....;}
var myIntv = setInterval(myF, 1500);
You could also do it using an anonymous function in one line as you're trying to do... do that this way:
var myIntv = setInterval(function(){document.body....;}, 1500);
I wouldn't suggest this as the solution to your problem. What it sounds like you want to do is manipulate the active DOM - not really change the UI. You likely need something like this:
var objs = document.getElementsBy__(); // ById/ByName/etc - depends on which ones you want
for (var i in objs){objs[i].ondblclick = objs[i].onmousedown;objs[i].onmousedown = undefined;} // just an example - but this should convey the basic idea
Even better, if you can use jQuery, then you'll be able to select the proper nodes more easily and manipulate the event handlers in a more manageable way:
$(".class.for.example").each(function(){this.ondblclick = this.onmousedown;this.onmousedown = undefined;}); // just an example - there are multiple ways to set and clear these
On one page of my website the user has the ability to choose and remove up to 2000 items through selecting multiple string representations of them in a dropdown list.
On page load, the objects are loaded onto the page from a previous session into 7 different drop-down lists.
In the window.onload event, the function looping through the items in the drop-downs makes an internal collection of the objects by adding them to a global array - This makes the page ridiculously slow to load, so, I'm fairly certain probably doing it wrong!
How else am I supposed to store these variables?
This is their internal representation:
function Permission(PName, DCID, ID) {
this.PName = PName;
this.DCID = DCID;
this.ID = ID;
}
where: PName is string. DCID is int. ID is int.
EDIT:
Thanks for the quick replies! I appreciate the help, I'm not great with JS! Here is more information:
'selectChangeEvent' is added to the Change and Click event of the Drop down list.
function selectChangeEvent(e) {
//...
addListItem(id);
//...
}
'addListItem(id)' sets up the visual representation of the objects and then calls :
function addListObject(x, idOfCaller) {
var arIDOfCaller = idOfCaller.toString().split('-');
if (arIDOfCaller[0] == "selLocs") {
var loc = new AccessLocation(x, arIDOfCaller[1]);
arrayLocations[GlobalIndexLocations] = loc;
GlobalIndexLocations++;
totalLocations++;
}
else {
var perm = new Permission(x, arIDOfCaller[1], arIDOfCaller[2]);
arrayPermissions[GlobalIndexPermissions] = perm;
GlobalIndexPermissions++;
totalPermissions++;
}
}
Still not enough to go on, but there are some small improvements I can see.
Instead of this pattern:
var loc = new AccessLocation(x, arIDOfCaller[1]);
arrayLocations[GlobalIndexLocations] = loc;
GlobalIndexLocations++;
totalLocations++;
which seems to involve redundant counters and has surplus assignment operations, try:
arrayLocations[arrayLocations.length] = new AccessLocation(x, arIDOfCaller[1]);
and just use arrayLocations.length where you would refer to GlobalIndexLocations or totalLocations (which fromt he code above would seem to always be the same value).
That should gain you a little boost, but this is not your main problem. I suggest you add some debugging Date objects to work out where the bottleneck is.
You may want to consider a design change to support the load. Some sort of paged result set or similar, to cut down on the number of concurrent records being modified.
As much as we desperately want them to be, browsers aren't quite there yet in terms of script execution speed that allow us to do certain types of heavy lifting on the client.
While I haven't tested this idea, I figured I'd throw it out there - might it be faster to return a JSON string from the server side, where your array is fully calculated on that side?
From that point, I'd wager that eval()'ing it (as evil as this may be) might be fast enough to where you could then write the contents onto the page, and your array setup would already be taken care of.
Then again, I suppose the amount of work it'd take the browser to construct the 2k new objects and inject them into the DOM wouldn't necessarily help the speed side of things in the end. At the end of the day, a design change is probably necessary, but sometimes we're stuck with what we've got, eh?