Java char array equality not functioning - java

I have an assignment that requires use of a socket. On the client and server side I have
char[] value= "END STREAM".toCharArray(), which signals the stream to shutdown.
Since I have both these arrays in the 2 different files, my intention is that the client sends the message value > the server. Then the server does the function
while(!Arrays.equals(clientSentence, value))
{
...
inFromClient.read(clientSentence, 0, length); //to read in from client side
.....
}
In essence, while it does not send the END STREAM message, keep reading. My issue is that the array equality does not work as intended. I even test this by doing
System.out.println(Arrays.equals(value, clientSentence));
System.out.println(new String(value));
System.out.println(new String(clientSentence));
and it prints
false
END STREAM
END STREAM
How can it be false when it is printing the same values. I have made sure that both arrays initialize to the same length so where is it going wrong? I have been stuck on this for hours and searched for answers but cannot find a solution. Thanks
EDIT: added my read function. I use a BufferedReader

On my box:
char[] x = "END STREAM".toCharArray();
char[] y = "END STREAM".toCharArray();
System.out.println(Arrays.equals(x, y));
System.out.println(Arrays.toString(x));
System.out.println(Arrays.toString(y));
works which makes me think a few things:
The arrays, as declared in your code, are not equal.
There is a character set incompatibility, you said you were using a BufferedReader and, if you're using the Files.newBufferedReader() functionality of Java 1.7, you need specify a charset when using it which may be causing a problem.
End of line issues either from cross platform systems or something else e.g. \r vs \n
Thinking a little more about it...it's probably #2, check this out for further information: http://docs.oracle.com/javase/tutorial/i18n/text/string.html

Related

Java - Socket needs delay to receive correct data?

I am writing a Java program using sockets to receive data from a C program.
The C program mallocs an integer array to fit the number of elements to be put inside. For example: {111,2,2,2,3,3} (111 is just a message header), so the int[] size is 6. (We free the array after sending is completed with a return value of 0 which is success). We print out the contents of the array, everything is displayed as expected: 111,2,2,2,3,3
However, we realize that in Java, we need to add a minor delay before reading from input stream, otherwise we can't get the correct values. E.g. if we don't put a Thread.sleep(2000) before input stream available, the value Java receive is like 111,0,0,0,3,3 (e.g. the value 2 is lost)
1) Does it affect Java if I send int array in C and ask Java to read int by int?
2) Why does the delay make the data accurate? We try playing around with 1000,1500 but only 2000 gives the most stable result
3) If in SomeAction.class, i put busy wait:
while (!pcClient.readMessage());
or
while (!pcClient.readMessage()) {}
it only go the while loop once and just break out? Whereas if I do this below , it works as intended:
while (!pcClient.readMessage()) {System.out.print("");}
1) Does it affect Java if I send int array in C and ask Java to read int by int?
When you ask Java to read it int by int, it basically waits for next 4 bytes available and builds an int value out of these 4 bytes
Looks like your Java client starts reading data before your C server starts writing it - that's why a delay of 2 seconds solve your problem
You can simply remove the if(dataIn.available() > 0) { } condition - dataIn.readInt() will block until the data is available on the wire
You're allocating and sending the wrong length. msg_queue is a pointer, and its size is irrelevant to the message length. sizeof msg_queue should be sizeof int throughout. You're sending too much data, so the receiver is getting out of sync.
Remove the pointless sleep and available() test. The subsequent reads will block for exactly the right length of time, unlike your sleep.
You don't need to clear the dynamic message befor freeing it. You don't even need to allocate the message dynamically, as its size is known at compile time.

Last few chars in a string sent over socket sometimes missing in Java network program

Right now, I'm trying to write a GUI based Java tic-tac-toe game that functions over a network connection. It essentially works at this point, however I have an intermittent error in which several chars sent over the network connection are lost during gameplay. One case looked like this, when println statements were added to message sends/reads:
Player 1:
Just sent ROW 14 COLUMN 11 GAMEOVER true
Player 2:
Just received ROW 14 COLUMN 11 GAMEOV
Im pretty sure the error is happening when I read over the network. The read takes place in its own thread, with a BufferedReader wrapped around the socket's InputStream, and looks like this:
try {
int input;
while((input = dataIn.read()) != -1 ){
char msgChar = (char)input;
String message = msgChar + "";
while(dataIn.ready()){
msgChar = (char)dataIn.read();
message+= msgChar;
}
System.out.println("Just received " + message);
this.processMessage(message);
}
this.sock.close();
}
My sendMessage method is pretty simple, (just a write over a DataOutputStream wrapped around the socket's outputstream) so I don't think the problem is happening there:
try {
dataOut.writeBytes(message);
System.out.println("Just sent " + message);
}
Any thoughts would be highly appreciated. Thanks!
As it turns out, the ready() method guaruntees only that the next read WON'T block. Consequently, !ready() does not guaruntee that the next read WILL block. Just that it could.
I believe that the problem here had to do with the TCP stack itself. Being stream-oriented, when bytes were written to the socket, TCP makes no guarantees as to the order or grouping of the bytes it sends. I suspect that the TCP stack was breaking up the sent string in a way that made sense to it, and that in the process, the ready() method must detect some sort of underlying break in the stream, and return false, in spite of the fact that more information is available.
I refactored the code to add a newline character to every message send, then simply performed a readLine() instead. This allowed my network protocol to be dependent on the newline character as a message delimiter, rather than the ready() method. I'm happy to say this fixed the problem.
Thanks for all your input!
Try flushing the OutputStream on the sender side. The last bytes might remain in some intenal buffers.
It is really important what types of streamed objects you use to operate with data. It seems to me that this troubleshooting is created by the fact that you use DataOutputStream for sending info, but something else for receiving. Try to send and receive info by DataOutputStream and DataInputStream respectively.
Matter fact, if you send something by calling dataOut.writeBoolean(b)
but trying to receive this thing by calling dataIn.readString(), you will eventually get nothing. DataInputStream and DataOutputStream are type-sensitive. Try to refactor your code keeping it in mind.
Moreover, some input streams return on invocation of read() a single byte. Here you try to convert this one single byte into char, while in java char by default consists of two bytes.
msgChar = (char)dataIn.read();
Check whether it is a reason of data loss.

What is C++ equivalent of Java StdIn.isEmpty()

I am trying to learn something basing on Java resource, and I want to adapt it to C++.
Source of Java has:
while( !StdIn.isEmpty())
{
//Take input from standard input, and process it...
}
In C++ the closest solution I could come up with was
while( cin >> someString)
{
//process someString...
}
However, the problem is, that cin returns state of object. There is no way I can put wrong input into std::string. This could have worked for ints, but not for string. Any equivalent function, or workarounds?
Thanks in advance.
With C++ iostreams, and also with C's stdio, you cannot tell whether a file (such as std::cin/stdin) will be empty if you were to try reading from it. The only way to find out is to actually read from the file, and then check whether the attempt succeeded.
(Yes, you could use some form of peek, but that's nowhere near as idiomatic or practical.)
So a standard method in C++ might look like this, processing entire lines of input at a time:
for (std::string line; std::getline(std::cin, line); )
{
// process "line"
}
The loop body will only execute if you succeeded at extracting one line from the input. Once the input runs out of data, the loop condition is no longer satisfied (i.e. the stream is no longer "good"), and the loop stops.
The same idea applies to C's fgets, as well as to unformatted std::istream::read() and fread, and to platform-specific functions like Posix's read(2): You always attempt to obtain input, then check whether you got any input, and only if you did do you proceed to consume the input.

Preventing "Null Byte Attacks" | Java

My initial understanding on this topic is that I need to prevent some junk characters available in request to avoid these attacks.
I have decided to solve this by Pattern matching for every request parameter before using it. Most of the posts available on internet talks about Null Byte and the example given shows how file IOs are the main victims of this attack. So following are my questions
Is File IOs are the only thing that null byte can affect or other operations are also victims of this attack?
What are the char/strings/patterns I need to take care if I want to filter my request parameter to be safe for null bye attacks? I have a list and I am sure it is not complete one. %00, \0, 0x00 in hex
The articles that I am referring to are:
http://projects.webappsec.org/w/page/13246949/Null%20Byte%20Injection
http://www.perlmonks.org/index.pl?node_id=38548
http://hakipedia.com/index.php/Poison_Null_Byte
Thanks in advance
So to make it more clear:
First post points out the vulnerability in java that I am talking about. String serverlogs.txt%00.db is allowed in java but when it comes to C/C++ this is serverlogs.txt as in C %00 would be replace by null byte causing the string to terminate after serverlogs.txt. So we should avoid such characters. This is what I am trying to figure out which such characters I should not allow.
String fn = request.getParameter("fn");
if (fn.endsWith(".db"))
{
File f = new File(fn);
//read the contents of “f” file
…
}
Have you tried it? I wrote this quick unit test:
#Test
public void test() throws Exception {
FileOutputStream out = new FileOutputStream("test.txt");
out.write("hello!".getBytes("utf-8"));
out.close();
String badPath = "test.txt\0foo";
File file = new File(badPath);
FileInputStream in = new FileInputStream(file);
System.out.println(StreamUtils.copyToString(in, Charset.forName("utf-8")));
}
Now, if the null character broke the string, I would expect to have the contents of my file printed to the console. Instead, I get a FileNotFoundException. For the record, this was using Java 1.7.0_40 on Ubuntu 13.04.
Update
Further investigation reveals this code in File#isInvalid:
final boolean isInvalid() {
if (status == null) {
status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
: PathStatus.INVALID;
}
return status == PathStatus.INVALID;
}
Not a bad question. I'm doubtful that this is a valid vulnerability on all platforms (for example, I believe Windows uses Pascal-style strings, not null-terminated strings, in its kernel), but I would not at all be surprised if some platforms and JVMs were in fact vulnerable to this kind of attack.
The key point to consider is where your strings are coming from, and what you're doing to those bytes before you interact with them as strings. Any bytes coming from a remote machine should always be assumed to be malicious until proven otherwise. And you should never take strings that come from over the Internet and try to turn them into paths on your local machine. Yes webservers like Apache do this, but that's also the most vulnerable code they have. The correct solution is: don't try to blacklist bad data (like null bytes), only whitelist good data.
You might also fight the issue of Null byte from the other angle!
in May 1013 Oracle fixed the problem: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8014846
So, upgrade to Java 8 or Java 7u40 and you are protected.
(Yes, i tested it!), it works!
If a link to my personal blog is not considered a spam, I'l drop it here:
http://crocode.blogspot.ru/2015/03/java-null-byte-injections.html
If I'm reading your question correctly, you want to prevent executable code from being injected into memory after the terminating null byte of a string.
Java ain't C.
Java doesn't use terminating null byes for its strings so you don't need to protect against this.

How do I read strings in J2ME?

I'm using the MIDP 2.0 (JSR 118) and I just noticed that there is no reader for strings in J2ME.
Does anyone know how you are supposed to read Strings from an InputStream or InputStreamReader in a platform independent way (i.e. between two java enabled cell phones of different models)?
Which profile are you using? The MID profile in JSR 118 specifies InputStreamReader (not StringReader, but that wouldn't help you read from an InputStream anyway).
EDIT: To reflect the change to the question :)
You use InputStreamReader.read(char[], int, int) and when you've read all you want to, create a new string from a char array. If you want to read a line at a time as you would from BufferedReader, you basically need to implement the functionality of BufferedReader yourself (keeping a buffer of "read but not consumed" chars) and keep reading until you hit a line break.
Alternatively have a look at DataInputStream.readUTF().
It does required that the string being read off the InputStream be encoded appropriately (as in by a corresponding DataOutputStream.writeUTF(String)) so it might not be what you're looking for - but it does work across different phones/models etc.
Well... I know this was a LONG time ago.
You need to do exactly what John said, and it is VERY simple. It almost took me 5 hours to figure this one out the first time...
I still wonder why j2ME didn't include something as essential as the BufferedReader method for sockets, it's not like the freakin cellphones will crash with it... and yes, I don't give a rat's ass if my app runs 1ms slower than it should.
(I'm just going to put the relevant code, I assume you know how to form classes and import the required libraries)
ServerSocketConnection listener
= (ServerSocketConnection)Connector.open("socket://:1235");
System.out.println("Waiting for connection...");
StreamConnection server = listener.acceptAndOpen();
InputStream is = server.openInputStream();
//Now comes the fake BufferedReader equivalent part
int ch = 0;
StringBuffer sb = new StringBuffer();
while ((ch = is.read()) != -1){
sb.append((char)ch);
if(sb.charAt(sb.length()-1) == 13 ) {
//Carriage return was received or ENTER was pressed
break; //Exit loop and print input
}
}
As you can see, the is.read() method will lock the thread till new input is received from the user ONE BYTE AT A TIME. This means if you use telnet to test, each keystroke will make the loop iterate once, hence, we simply concatenate char by char in a StringBuffer until char 13 is received.
System.out.println(sb.toString());
I hope this helps people trying to do a socket server on j2ME. I already crafted a fully functional multithreaded version of this for blackberry, in case anyone needs it.
Would you be able to provide an example of this?
You use InputStreamReader.read(char[], int, int) and when you've read all you want to, create a new string from a char array. If you want to read a line at a time as you would from BufferedReader, you basically need to implement the functionality of BufferedReader yourself (keeping a buffer of "read but not consumed" chars) and keep reading until you hit a line break.

Categories