Does Java String.format() prevent String injection? [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have been preparing for technical interview. So in one thing I am just not sure. If I write for example
try {
...
} catch (InterruptedException ie) {
throw new IllegalStateException(String.format("Player [%s]: failed to reply message [%s]"), ie);
}
Does this prevent already String injection? or Do I have to write like following:
String errorMsg = String.format("Player [%s]: failed to reply message [%s]");
throw new IllegalStateException(errorMsg, ie);

There is no difference between the two snippets. Neither protects against 'string injection'.
There are only 4 non-boneheaded mitigations against string injection attacks:
Ensure that where-ever the strings end up, it is impossible for this to be a security issue in any way or form. For example, if your data is going to a binary file where all system operators are aware the contents are straight from the web, it doesn't matter what's uploaded.
Do not render the string at all. Throwing the baby out with the bathwater.
Use a whitelist. If the string consists solely of these allowed things, allow it. By default, do not allow it.
Use escapers.
Honourable mention for the concept of blacklisting: Have a list of known-malicious stuff, and allow all strings unless they contain something on the blacklist. This is bone headed and should never be used. For example, if you scan incoming data for <script>, you messed up. Don't do this. It doesn't work. Blacklists are trivially bypassed. Whitelists are what you're looking for.
The vastly most common strategy is the 4th: Escapers. For example, when you have a web server that takes in a username and a user's telephone number and a user's full name, and then renders all this information back out on their public website, then:
The phone number should be mitigated using the whitelist strategy. A single +, digits in the range 0-9, spaces, dashes, and nothing else. If that's what the input is like, allow it. Otherwise don't.
The user's real name should be mitigated with escaping: Take the data as provided and inject it verbatim into your database, but treat this data as tainted in all interactions with that data: For example, when rendering that public page, the 'full name' string needs to be washed through an HTML escaper which e.g. replaces all < with <.
Your code doesn't do any of these 4 things (either version of it).
In general it is an extremely bad idea to consider the string returned by an exception's .getMessage() to be already 'safe' (escaped / passed the whitelist verifier). Instead, the code that invokes .getMessage() needs to apply one of the 4 mitigations as explained above.

Related

Removing alphabetical characters from a string [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 months ago.
This post was edited and submitted for review 8 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I am new to java. Trying to create a function to remove a given string "arg" from myString which is previously set and return a new string not affecting myString. I believe i could solve this problem if it was not for all non alphabetical character of arg should remain in the string. so if arg has a 7 in it that should still be included in the final string. characters being removed are case insensitive as well.
I have edited the previous code and post, i can now run my code but I am not getting the correct results, I am trying to remove all numbers from arg before using it to remove all the characters. myString method is previously defined and working properly to return a string.
For examplecurrent string "my lucky numbers are 6, 8, and 19.", calling remove("ra6") would return "my lucky numbes e 6, 8, nd 19."
or "my lucky numbers are 6, 8, and 19.", calling remove("6,.") would return "my lucky numbers are 6, 8, and 19."
thank you!
public String remove(String arg) {
char[] charArray=arg.toCharArray();
String result="";
String newString="";
for (int i = 0; i < charArray.length; i++) {
if (!Character.isDigit(charArray[i])) {
result = result + charArray[i];
return result;}}
if (myString==null || myString=="") {
this.myString="";}
if (myString!=null) {
newString= myString.replaceAll(result,"");}
return newString;
}
Here is one way using streams. Just create a stream of characters via the chars() method and allow only letters to pass thru. Then each character to a String and join them together. Then remove that result from the original passed string.
String myString = "abcdTLK123efgh";
String arg = "TLK###123";
String result = remove(arg, myString);
System.out.println("Result = " + result);
prints
Result = abcd123efgh
The method
I modified the method to accept two strings.
the one to remove characters(arg).
and the from which to remove modified arg from myString
it works by
streaming all the characters of arg.
filtering out all but letters and digits
joining them as a string.
and then removing that filtered string from the myString.
public static String remove(String arg, String myString) {
if (myString == null || myString.isBlank()) {
return "";
}
return arg.chars().filter(
ch -> Character.isLetter(ch))
.mapToObj(Character::toString)
.collect(Collectors.collectingAndThen(
Collectors.joining(),
str -> myString.replace(str, "")));
}
Note: If myString is null then assigning an empty string to it will contain nothing to change. Nor an initial empty string. So I just returned an empty String if those conditions existed.
I believe i could solve this problem if it was not for all non alphabetical character of arg should remain in the string.
The good news is that you can solve it yourself.
The bad news is that the code above is in such a mess that it would be difficult for you to fix it by yourself. (Given your current level understand of Java syntax, way of working, etcetera.)
(Also, there is a long more wrong than the "if it were not for ..." ...)
So here is what I advise you to do.
Save a copy of the current version of the (entire) class somewhere safe so that you can look it again if you need to, or revert to it.
Develop a model of what the method needs to do and how it will do it; see below.
Delete all lines of code between the first { and last } shown in the question. Yes. Delete them.
Compose the new version of the code, one line at a time. As follows:
Add a line.
Compile the code (or let the IDE compile it for you).
Read the compilation error(s) that just appeared.
Understand the compilation errors.
Make the necessary changes to fix the compilation errors. Don't rely on your IDE's facility for suggesting corrections. (The IDE doesn't understand your code, what you are going to add next, or what you are trying to achieve. Its suggestions are liable to be unhelpful or even wrong.)
Repeat until you have dealt with all of the compilation errors that were introduced.
Now you are ready to add another line.
Once you have a complete method, you can then try to run it.
You will most likely find that the code doesn't work. But at least it will be valid Java code. And in the process of doing 4. above, you will (hopefully!) have learned enough Java syntax to be able to read and understand the code that you wrote. And 2. will help you understand what the code you are writing should do.
My other observation is that it looks like you have been adding and removing statements to this code with no clear understanding of what they do or what needs to happen. Maybe you started with some code that did something else ... correctly ... but it is hard to tell now.
Changing things randomly to try to make the code work is not a sensible approach. It rarely works. You need to have a model (or plan) in your head or on paper (e.g. as pseudo-code or flowcharts) about how the code ought to work.
Programming is about 1) developing the model, then 2) translating the model into code. The first part is the hard (and interesting) part. But if you skip the first part, the second part is an essentially random process, and unlikely to succeed.
The problem with starting with someone else's code is that you risk not developing a mental model of how that code works. Let alone the model that you are aiming for.
Finally, a professional programmer will use a version control system for their source code, and make relatively frequent commits of their code to their repository. Among other things, that allows them to quickly "roll back" to an earlier version if they need to, or keep track of exactly what they changed.
It is probably too early for you to learn about (say) using Git ... but it would help you solve your problem if you could just "roll back" all of the changes where you were "messing" with the code to get it to work.

Get last modified file with matching name Java 8 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm trying the retrieve the last modified file name with a matching pattern starts with Order_ and there should not be any hidden files, however it throws compilation error.
try {
File dir = new File("< dir >");
if (!dir.isDirectory()) {
Optional<File> op = Arrays.stream(dir.listFiles(File::isFile))
.max((f1, f2) -> Long.compare(f1.lastModified(), f12lastModified()))
.filter(fl -> fl.getName().startsWith("Order_") && !fl.getCanonicalPath().endsWith("~"))
; // Unhandled exception compilation error for canonicalPath method
}
} catch (Exception e) {
}
Exception: Unhandled exception: java.io.IOException
Any ideas would be greatly appreciated.
This feels like lambda abuse (using a hammer to butter your toast instead of, you know, a butter knife, because you just bought it and it's all shiny and new).
.max() returns either 1, or 0, elements, in the form of an Optional. you then filter that optional to check if the naming is right.
In other words, if the most recently modified file so happens to not start with Order_, this all returns Optional.NONE which surely wasn't your intent. You want to flip your max and your filter line.
More generally, you don't want to do this with lambdas. Inline Lambdas are the lesser evil - they are not exception transparent, not mutable local variable transparent, and not control flow transparent.
These 3 properties are fantastic when a lambda represents code that will run in some other context (e.g. another thread or much later). They are downsides when the code is going to be run then and there.
That means that when a lambda-based strategy and a non-lambda-based strategy for an inline code concept are roughly equally good, then you should prefer the non-lambda-based strategy. This becomes particularly poignant here, as the code is using obsolete API (the old java.io.File API, instead of the newer java.nio.file API).
In this case, .getCanonicalPath() is slightly odd behaviour: The only functional difference between invoking fl.getName().endsWith(...) and fl.getCanonicalPath().endsWith(...) is that the latter will first follow the link if the referenced 'file' is a soft-link.
That sounds like soft-links matter, and if they matter, you don't want this API as it is wonky and ill defined in the face of soft-links. The new API deals with it better, you'd want to use that (java.nio.file.Files's walk method, for example). If soft linking doesn't matter, then it's easy: Replace .getCanonicalPath() with .getName() and all is well. Well, after you fix your bug and flip the filter and max lines back in their right positions.
Note also that .getCanonicalPath() is slow - it needs to hit the disk, or at least, it might. (It will if it is a soft-link; the API doesn't define whether it will in other cases. The JVM impl is free to hit disk on some OSes and not on others. It may run blazingly fast on your system and run dog slow on another, making it hard to test).

How slow/fast is String concatenation in Java relative to other compiled languages? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm just getting started with Java and while reading through this guide I noticed the following snippet, describing a recent update to the Junit framework.
We can now write assertion messages in a lambda in JUnit 5, allowing
the lazy evaluation to skip complex message construction until needed:
#Test
public void shouldFailBecauseTheNumbersAreNotEqual_lazyEvaluation() {
Assertions.assertTrue(
2 == 3,
() -> "Numbers " + 2 + " and " + 3 + " are not equal!");
}
As someone new to Java this feels like a large implementation just to get around string concatenation.
Are evaluating strings in Java really that slow (relative to other languages?). How does it compare to other compiled languages like C, Golang, etc..?
The point is: there is no lazy string formatting in Java.
Meaning, in languages like C you might see things such as:
#define debug_print...
( see some real world examples here )
The idea is to define a macro to which you pass a complicated string. But the compiler makes sure that code gets only generated for situations that actually that string to be present.
Meaning: when using debug_print(), that complicated string concat that is might be required to build the messages passed to the macro call only happens when the message is really needed! The message is concatenated lazily.
In Java, we simply have no way to express that. You always have to go
if (someCondition) {
then pull together that large string
which isn't nice, especially when doing it for tracing. Some people in our group write that code, and it is just overly annoying that each and any trace statement has that leading if statement. That renders your whole code much less readable.
Therefore: this is not at all about the cost of string concats. It is about only spending the required CPU cycles if that string is truly needed.
And to answer the actual question: in the end, when that code gets invoked often enough, the JIT will turn it into carefully optimized machine code anyway. Thus: the actual string concat is not the issue.
In other words: you don't think of "performance" for Java in terms of source code. What matters is what happens at runtime, by the JIT.
Here's the bottom line. Starting out in Java, don't worry about minor performance issues like String concatenation. It may be a small issue for a large application server where lots of String concatenation is done but the results are not used. An example would be logging, where the log level of causes the event to be ignored. Also, Java uses a StringBuilder to concatenate a series of literals separated by the "+' operator, which is reasonably performant.

converting nested FOR loops into stream using stream Java 1.8 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Would like to know , how to convert two nested FOR loops using java 1.8 stream .
Scenario:
variable usrAccountId - sent by User and
variable accountDetailsinRedis- actually accounts presents in database.
I am actually comparing accountId sent by user is same as accountId in the database.
This is below code , I have two nested FOR loops , I want to convert it into Java 1.8 using Stream . Anyone has any idea.
for (int usrAccountId : acctIDstoValidate) {
for (Account account : accountDetailsinRedis) {
According to your actual logic, you pass multiple ids to match.
So you could have multiple matchings.
Stream on acctIDstoValidate, then chain it with a flatMap() on accountDetailsinRedis to do the filter on the id.
Collection<Integer> acctIDstoValidate = ...;
Collection<Account> accountDetailsinRedis = ...;
List<Account> matching = acctIDstoValidate.stream()
.flatMap(idToValidate-> accountDetailsinRedis.stream()
.filter(b-> b.getId() == idToValidate))
.collect(Collectors.toList());
Can you give more detail about what are you doing inside loop?
For me, I don't what are you doing here, therefore that I just suggest You can use like this:
acctIDstoValidate.forEach(item -> {
accountDetailsinRedis.forEach({
//TODO
})
});
some thing like below code snippet
With a bot of guesswork, assuming both variables you have in your example are collections, this might be what you are after:
acctIDstoValidate.removeAll(
accountDetailsinRedis.stream()
.map(Account::getId)
.collect(Collectors.toList())
)
And you end up with invlid ids left in: acctIDstoValidate
Also note that your variable naming xan be improved, to consistently use account instead of sometimes shortening it to acct, and not capitalizing ID for better camel casing: accountIdsToValidate

Academic-setting clarification of the term "Standard Input" in Java and verifying Input

Was instructed, for a university-level assignment, to receive user input through "standard input". Google was a bit scarce as to what precisely this means.
While I could (and for the sake of my grade, will) go to my professor for clarification, I figured I would ask Stack Overflow so if anyone in the future has the same question they can find this and do without the research I performed; additionally, I appreciate the history lesson some Stack Overflow contributors provide.
Basically, what I found was receiving user input was originally done via standard input methods (hardware). However, and this is where things get complicated, now the process has been abstracted. Instead of requiring hardware, now, through something called redirection/pipelining, we can modify where the input will come from.
In addition to clarifying what the above means, I, personally, am interested in a Java-specific response.
Simply put, there are three "common" ways of receiving user input in Java
SO Source: BufferedReader vs Console vs Scanner
Basically, what I got from the above, is that the differences involve optimization for what you intend to do with the input and how the input is stored/treated, in terms of whether it is received as the ASCII Integer or whatever.
My question is are all three of the above methods considered standard input? Is there a way of obtaining user input NOT through standard input? By user input I mean something the user inputs manually upon program execution, not transferring data from a file or anything like that.
Furthermore, when receiving input in the above way, is it worth checking for null?
Example:
Scanner a = new Scanner(System.in);
String testInput = a.nextLine();
if (testInput == null)
How can something input by the user ever point to nothing in memory (i.e. null?) is this ever possible?

Categories