Why is eval evil in makefiles - makefile

I have had several people tell me at this point that eval is evil in makefiles. I originally took their word for it, but now I'm starting to question it. Take the following makefile:
%.o:
$(eval targ=$*)
echo making $targ
%.p:
echo making $*
I understand that if you then did make "a;blah;".o, then it would run blah (Which could be an rm -rf \, or worse). However, if you ran make "a;blah;".p you would get the same result without the eval. Furthermore, if you have permissions to run make, you would also have permissions to run blah directly as well, and wouldn't need to run make at all. So now I'm wondering, is eval really an added security risk in makefiles, and if so, what should be avoided?

Why is eval evil?
Because it grants a whole power of language to things you actually don't want to give that power.
Often it is used as "poor man's metaprogramming" to construct some piece of code and then run it. Often it looks like eval("do stuff with " + thing) - and thing is only known during runtime, because it gets supplied from outside.
However, if you don't make sure that thing belongs to some tiny subset of language you need in that particular case (like, is a string representation of one valid name), your code would grant permissions to stuff you didn't intend to. For example, if thing is "apples; steal all oranges" then oranges would be stolen.
If you do make sure that thing belongs to some subset of language you actually need then 2 problems arise:
You are reimplementing language features (parsing source) which is not DRY and is often a sign of misusing a language.
If you resort to this that means simpler means are not suitable and your use case is somewhat complicated which makes validating your input harder.
Thus, it's really easy to break security with eval and taking enough precautions to make it safe is hard, that's why if you see an eval you should suspect possible security flaw. That's just a heuristic, not a law.
eval is a very powerful tool - as powerful as the whole language - and it's too easy to shoot your leg off with it.
Why this particular use of eval is not good?
Imagine a task that requires making some steps that depend on a file. Task can be done with various files. (like, user gives Virtualbox image of a machine that is to be brought up and integrated into existing network infrastructure)
Imagine, say, lazy administrator that automated this task - all commands are written in a makefile because it fits better than sh script (some steps depend on other and sometimes don't need to be re-done).
Administrator made sure that all commands are ok and correct and had given sudoers permission to run make with that specific makefile. Now, if makefile contains string like yours then using properly crafted name for your Virtualbox image you could pwn the system, or something like that.
Of course, I had to stretch far to make this particular case a problem, but it's a potential problem anyway.
Makefiles usually offer simple contracts: you name the target and some very specific stuff - written in makefile - gets done. Using eval the way you've used it offers a different contract: the same stuff as above but you also can supply commands in some complicated way and they would get executed too.
You could try patching the contract by making sure that $* would not cause any trouble. Describing what that means exactly could be an interesting exercise in language if you want to keep as much flexibility in target names as possible.
Otherwise, you should be aware of extended contract and don't use solutions like this in cases where that extension would cause problems. If you intend your solution to be reusable by as many people as possible, you should make its contract cause as little problems as possible, too.

Related

Why don't makefiles behave more like shell scripts within recipes?

I find makefiles very useful, and the header of each recipe
<target> : [dependencies]
is helpful. Within a recipe, the prefixes # and - are useful, as well as the automatically-defined variables like $# and $?. However, besides that, I find the way of coding the actual recipe to be strange and unhelpful. There are so many questions on StackOverflow along the lines of "how to do this in a makefile" for something that's simple (or at least more familiar) to do in bash.
Is there a reason why the recipe contents are not just interpreted as a regular shell script? Reading the manual pages, there seems to be many tools with equivalent functionality to a shell script but with different syntax. I end up specifying .ONESHELL and escaping $ with $$, or sometimes just call a script from the recipe when I can't figure out how to make it work in a makefile. My question is whether this is just unfortunate design, or are there are important features of makefiles that force them to be designed this way?
I don't really know how to answer your question. Probably that means it's not really appropriate for StackOverflow.
The requirement for using $$ instead of $ is obvious. The reasoning for using a separate shell for each logical line of a makefile instead of passing the entire recipe to a single shell, is less clear. It could have worked either way, and this is the way it was chosen.
There is one advantage to the way it works now, although maybe most people don't care about it: you only have to indent the first recipe line with TAB, if you use backslash newline to continue each line. If you don't use backslash newline, then every line has to be indented with TAB else you don't know where the recipe ends.
If your question is, could Stuart Feldman have made very different syntax decisions that would have made it easier to write long/complex recipes in makefiles, then sure. Choosing a more obscure character than $ as a variable introducer would reduce the amount of escaping (although, shell scripting uses pretty much every special character somewhere so "reduce" is the best you can do). Choosing an explicit "start/stop" character sequence for recipes would make it simpler to write long recipes, possibly at the expense of some readability.
But that's not how it was done.

Is it considered good practice to use binaries with their full pathname in shell scripts?

I would like to write shell scripts in a way considered good practice.
An experienced programmer friend advised to use the full pathname for each external command to avoid problems with aliases, functions et al, happening to use the same name as an existing binary, maybe even for malicious reasons. I understand the argument, but short commands (in $PATH) get long very quickly, like:
sudo socketfilterfw --setloggingmode on
becomes
/usr/bin/sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setloggingmode on
This makes quickly grasping what a script does a little harder for me. But maybe I just need to get used to this.
Looking at examples of scripts on github, I do find people doing the same, but most do not.
Is using the full path to a binary considered "good practice"?
No, the generally recommended practice is to rely on the PATH to be correct; or sometimes, if you know the expected location of a program which is not typically already on the PATH, to augment the PATH;
PATH="$PATH:/usr/libexec/ApplicationFirewall"
sudo socketfilterfw --setloggingmode on
Hardcoding the path to a binary means you cannot easily replace it with a customized wrapper for local administrative purposes or debugging; it simply makes everyone's lives harder.
As an aside, a common (but harmless) error is to needlessly export the PATH. Unless you need child processes of the script to inherit the variable, there is no need to export it. (And in practice, you can often be fairly sure the user will already have done that in their login shell; though for system processes which are not always run from an interactive shell, this is not necessarily a given.)

What are possible pros and cons for prefixing folders with digits?

My company strongly suggests to use subfolder names prefixed by digits for larger projects. This is recorded in the companies code convention articles.
This should look something like this
ApplicationRoot/
SomeSubFolder
00_SubSubFolder/
01_SubSubFolder/
02_SubSubFolder/
AnotherSubFolder
00_SubSubFolder/
01_SubSubFolder/
02_SubSubFolder/
Somehow this feels like an useless overhead to me but I have no valid arguments against that.
Maybe more experienced people can tell me about scenarios which show why this is a bad habit or tell my why it is good - besides the possibility to force the folder to be in a certain order?
it's useful only if the order is important (e.g. order of running scripts). otherwise it's bad (in my opinion). the arguments are:
some products don't allow it. e.g. java package structure maps directly to directory structure. but package name can't start with a digit.
can't use convention over configuration. some tools help you a lot with software development and they assume you are doing it same way as rest of the world (because it's a good practise). you will have a lot of configuration to make them accept your structure (e.g. maven)
human perception. we look for data by names, not by numbers. when i navigate to a file in e.g. krusader/total commander and i have a dozen of dirs i type a letter because i know the folder name.
confusion. if those numbers mean nothing then it introduces confusion to other people. they will always ask 'why', they will always affraid to modify add, remove because they will think someone did it because of some very important reason. that's a clear violation of KISS and least surprise principles (such things heavily affect new developers entry barrier)
no flexibility. sometimes it's good to have custom folder names. for whatever reason, e.g automatic search of configuration in multiple directories (often used in java/spring). but heaving such naming convention it's more difficult to do it. sometimes when you want to use automatic naming translation it also may be harder as your target format may not support names starting with digits (e.g. logins)
overhead. if there is no reason to keep it then any overhead should be removed. again: KISS
last but not least. developer/architect is always the one that makes decisions about software design, layout, used techniques etc. if his hands are tights because of senseless rules invented by non-technical bureaucrats from the previous epoch, that's nothing but troubles

How to safely let users run arbitrary Ruby code?

I realize this sounds a little crazy, but I'm working on a project for which I need a server to run user-provided Ruby code and return the result.
I'm looking to prevent something like this:
system("rm -rf /")
eval("something_evil")
# etc...
I'm sure there must be some reasonably safe way to do this, as it already exists at places like tryruby.org. Any help is greatly appreciated, thanks!
Three suggestions:
1) Take a look at Ruby taint levels. This provides some degree of protection against, eval('evil_code') type things, etc.
2) Unless user's actually need access to the local file system, use something like fakefs
3) No matter what else you do follow Tronic's suggestion (can be a pain to setup, but limited chroot jails are about the only way to make absolutely sure that user's cannot access resources you don't explicitly want them to).
Run the program ptraced with a whitelist of allowed syscalls, as user/group nobody, with resource limits (memory usage etc), in a minimal chroot.
A "blank slate" is an object stripped of (most of) its methods.
A "clean room" is an object within which you evaluate potentially unsafe room.
If you evaluate the code in a "clean room" which is also a "blank slate," cranking the safe level up as high as it will go, you will afford yourself a great deal of protection. Nothing in security is sure, so this should be considered a layer in your security, not necessarily the only layer.
This answer shows how to do it.
I had the same problem but then came across eval.so and decided to write an API wrapper for it, called Sandie. It's as easy as:
sandie = Sandie.new(language: 'ruby')
# => #<Sandie:0x00000002e30650>
sandie.evaluate(code: 'puts "hello world"')
# => {"stdout"=>"hello world\n", "stderr"=>"", "wallTime"=>487, "exitCode"=>0}
It also supports a whole lot of other languages as well like C#, Perl, Lua, and Java.

Best way to get rid of hungarian notation?

Let's say you've inherited a C# codebase that uses one class with 200 static methods to provide core functionality (such as database lookups). Of the many nightmares in that class, there's copious use of Hungarian notation (the bad kind).
Would you refactor the variable names to remove the Hungarian notation, or would you leave them alone?
If you chose to change all the variables to remove Hungarian notation, what would be your method?
Refactor -- I find Hungarian notation on that scale really interferes with the natural readability of the code, and the exercise is a good way of getting familiar with what's there.
However, if there are other team members who know the code base you would need consensus on the refactoring, and if any of the variables are exposed outside of the one project then you will have to leave them alone.
Just leave it alone. There are better uses of your time.
Right click on the variable name, Refactor -> Rename.
There are VS add-ins that do this as well, but the built-in method works fine for me.
What would I do? Assuming that I just have to maintain the code and not rewrite it any significant way? Leave it well alone. And When I do add code, go with the existing style, meaning, use that ugly Hungarian notation (as dirty as that makes me feel.)
But, hey, if you really have a hankerin' fer refactorin' then just do a little at a time. Every time you work on it spend ten minutes renaming variables. Tidying things up a little. After a few months you might find it's clean as a whistle....
Don't forget that there are two kinds of Hungarian Notation.
The original Charles Simonyi HN, later known as App's Hungarian and the later abomination called System Hungarian after some peckerhead (it's a technical term) totally misread Simonyi's original paper.
Unfortunately, System HN was propagated by Petzold and others to become the more dominant abortion that it is rightfully recognised as today.
Read Joel's excellent article about the intent of the original Apps Hungarian Notation and be sorry for what got lost in the rush.
If what you've got is App's Hungarian you will probably want to keep it after reading both the original Charles Simonyi article and the Joel article.
If you've landed in a steaming pile of System Hungarian?
All bets are off!
Whew! (said while holding nose) (-:
if you're feeling lucky and just want the Hungarian to go away, isolate the Hungarian prefixes that are used and try a search and replace in file to replace them with nothing, then do a clean and rebuild. If the number of errors is small, just fix it. If the number of errors is huge, go back and break it up into logical (by domain) classes first, then rename individually (the IDE will help)
I used to use it religiously back in the VB6 days, but stopped when VB.NET came out because that's what the new VB guidelines said. Other developers didn't. So, we’ve got a lot of old code with it. When I do maintenance on code I remove the notation from the functions/methods/sub I touch. I wouldn't remove it all at once unless you've got really good unit tests for everything and can run them to prove that nothing's broken.
How much are you going to break by doing this? That's an important question to ask yourself. If there are a lot of other pieces of code that use that library, then you might just be creating work for folks (maybe you) by going through the renaming exercise.
I'd put it on the list of things to do when refactoring. At least then everyone expects you to be breaking the library (temporarily).
That said, I totally get frustrated with poorly named methods and variables, so I can relate.
I wouldn't make a project out of it. I'd use the refactoring tools in VS (actually, I'd use Resharper's, but VS's work just fine) and fix all the variables in any method I was called upon to modify. Or if I had to make larger-scale changes, I'd refactor the variable names in any method I was called upon to understand.
If you have a legitimate need to remove and change it I would use either the built in refactoring tools, or something like Resharper.
However, I would agree with Chris Conway to a certain standpoint and ask you WHY, yes, it is annoying, but at the same time, a lot of the time the "if it aint't broke done't fix it" method is really the best way to go!
Only change it when you directly use it. And make sure you have a testbench ready to apply to ensure it still works.
I agree that the best way to phase out hungarian notation is to refactor code as you modify it. The greatest benefit of doing this kind of refactoring is that you should be writing unit tests around the code you're modifying so that you have a safety net instead of crossing your fingers and hoping that you don't break existing functionality. Once you have these unit tests in place, you are free to change the code to your heart's content.
I'd say a bigger problem is that you have a single class with 200(!) methods!
If this is a much depended on / much changed class then it might be worth refactoring to make it more usable.
In this, Resharper is an absolute must (you could use the built in refactoring stuff, but Resharper is way better).
Start finding a group of related methods, and then refactor these out into a nice small cohesive class. Update to conform to your latest code standards.
Compile & run your test suite.
Have energy for more? Extract another class.
Worn out - no trouble; come back and do some more tomorrow. In just a few days you'll have conquered the beast.
I agree with #Booji -- do it manually, on a per-routine basis when you're already visiting the code for some other good reason. Then, you'll get the most common ones out of the way, and who cares about the rest.
I was thinking of asking a similar question, only in my case, the offending code is my own. I have a very old habit of using "the bad kind" of Hungarian from my FoxPro days (which had weak typing and unusual scoping) — a habit I've only recently kicked.
It's hard — it means accepting an inconsistent style in your code base. It was only a week ago I finally said "screw it" and began a parameter name without the letter "p". The cognitive dissonance I initially felt has given way to a feeling of liberty. The world did not come to an end.
The way I've been going about this problem is changing one variable at a time as I come across them, then perform more sweeping changes when you come back to do more in-depth changes. If you're anything like me, the different nomenclature of your variables will drive you bat-shiat crazy for a while, but you'll slowly become used to it. The key is to chip away at it a little bit at a time until you have everything to where it needs to be.
Alternatively, you could jettison your variables altogether and just have every function return 42.
It sounds to me like the bigger problem is that 200-method God Object class. I'd suggest that refactoring just to remove the Hungarian notation is a low-value, high-risk activity in of itself. Unless there's a copious set of automated unit tests around that class to give you some confidence in your refactoring, I think you should leave it well and truly alone.
I guess it's unlikely that such a set of tests exists, because a developer following TDD practices would (hopefully) have naturally avoided building a god object in the first place - it would be very difficult to write comprehensive tests for.
Eliminating the god object and getting a unit test base in place is of higher value, however. My advice would be to look for opportunities to refactor the class itself - perhaps when a suitable business requirement/change comes along that necessitates a change to that code (and thus hopefully comes with some system & regression testing bought and paid for). You might not be able to justify the effort of refactoring the whole thing in one go, but you can do it piece by piece as the opportunity comes along, and test-drive the changes. In this way you can slowly convert the spaghetti code into a cleaner code base with comprehensive unit tests, bit by bit.
And you can eliminate the Hungarian as you go, if you like.
I am actually doing the same thing here for an application extension. My approach has been to use VIM mappings to search for specific Hungarian notation prefixes and then delete them and fix capitalization as appropriate.
Examples (goes in vimrc):
"" Hungarian notation conversion helpers
"" get rid of str prefixes and fix caps e.g. strName -> name
map ,bs /\Wstr[A-Z]^Ml3x~
map ,bi /\Wint[A-Z]^Ml3x~
"" little more complex to clean up m_p type class variables
map ,bm /\Wm_p\?[A-Z]^M:.s/\(\W\)m_p\?/\1_/^M/\W_[A-Z]^Mll~
map ,bp /\Wp[A-Z]^Mlx~
If you're gonna break code just for the sake of refactoring, I would seriously consider leaving i alone, specially, if you are going to affect other people in your team who may be depending on that code.
If your team is OK with this refactoring, and investing your time in doing this (which may be a time-saver in the future, if it means the code is more readable/maintainable), use Visual Studio (or whatever IDE you are using) to help you refactor the code.
However, if a big change like this is not a risk your team/boss is willing to take, I would suggest a somewhat unorthodox, half-way approach. Instead of doing all your refactoring in a single sweep, why not refactor sections of code (more specifically, functions) that need to be touched during normal maintenance? Over time, this slow refactoring will bring the code up to a cleaner state, at which point you can finish the refactoring process with a final sweep.
Use this java tool to remove HN:
Or just use "replace"/"replace all" with regex like below to replace "c_strX" to "x":
I love Hungarian notation. Don't understand why you would want to get rid of it.

Resources