Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
ivantod
Mar 27, 2010

Mahalo, fuckers.

Jabor posted:

I think ivantod is mainly talking about the unnecessary inheritance you're being asked to implement. Using inheritance like this is an approach that is often tantalizingly easy to begin with, but ultimately makes programs very inflexible and difficult to maintain, and has fallen out of favour in many professional circles for that reason.

It's challenging to offer criticism here because a lot of the bigger issues are likely to have been dictated to you by the assignment rather than something you have control over.

For example, two fundamental isues are:
- You wouldn't really write a CarLot class to begin with. You'd just have a List<Car>, and some utility methods that accept a List<Car>. Some of the methods you've been asked to implement you wouldn't even write in the first place - you'd just use some of the more generic collections methods that accomplish the same thing.
- You wouldn't write a mutable Car class with getters and setters. You'd write an immutable (can never be changed) Car class, that only has getters. For state that is expected to change, such as whether the car has been sold, you might track that in some other location rather than as a field in the Car class.

But it's likely that both of those decisions aren't ones that you made - they're things dictated to you, that you need to do even though they're not modern best practice.

Correct.

Sorry for not being 100% clear, but I was upset with the fact that the people who are supposed to be teaching the OP are telling them that is a good way to do things (e.g. by inheriting from ArrayList and stuff). The criticism was not intended against the OP, who I assume is doing their best to try to pass this class as is not at all to blame here for the stupid assignment they were given.

OP, I'm sorry, I absolutely was not indending to criticise you, sorry that it came across that way! I'm just angry at your teachers!

ivantod fucked around with this message at 15:23 on Dec 1, 2021

Adbot
ADBOT LOVES YOU

Mycroft Holmes
Mar 26, 2010

by Azathoth

Jabor posted:

It sounds like you need to make CarLot extend ArrayList<Car>, delete the inventory field, and then just refer to this anywhere you were previously referring to inventory. If it sounds dumb as hell then you're right, it is, because the assignment is dumb as hell.

And probably fix all the places you're trying to copy the list so that they actually make a copy.

Ok, here is the changed CarLot:

code:
package carlot;
import java.io.*;
import java.util.*;

public class CarLot extends ArrayList<Car>{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	File file = new File("c:\\cars.csv");
    
	public ArrayList<Car> getInventory() {
		return this;
	}

	public void setInventory(ArrayList<Car> inventory) {
		this = inventory;
	}
	
	public void addCar(String ID, int mileage, int MPG, double cost, double salesprice) {
		Car c = new Car(ID, mileage, MPG, cost, salesprice);
	    this.add(c);
	}
	
	public void sellCar(String identifier, double priceSold) throws Exception{
		Car c = null; boolean Sold=false;
	    ListIterator<Car> it = this.listIterator();
	    while(it.hasNext()) {
	      c = (Car)it.next();
	      if(!c.isSold() & identifier.equalsIgnoreCase(c.getID())) {
	        c.sellCar(priceSold);
	        Sold = true;
	           }
	       }
	       if(!Sold) {
	           throw new Exception("Car can't be sold.");
	       }
	}
	
	 public Car findCarByIdentifier(String identifier) {
	       Car c = null;
	       ListIterator<Car> it = this.listIterator();
	       while(it.hasNext()) {
	           c = (Car)it.next();
	           if(identifier.equalsIgnoreCase(c.getID())) {
	               break;
	           }
	       }
	       return c;
	   }
	   public ArrayList<Car> getCarsInOrderOfEntry() {
	       ArrayList<Car> inventoryCopy = this;
	       return inventoryCopy;
	   }
	   public ArrayList<Car> getCarsSortedByMPG() {
	       ArrayList<Car> inventoryCopy = this;
	      inventoryCopy.sort(Comparator.comparingInt(Car::getMPG));
	       return inventoryCopy;
	   }
	   public Car getCarWithBestMPG() throws Exception{
	       Car bestMPGCar = this.get(0); Car c = null;
	       ListIterator<Car> it = this.listIterator();
	       while(it.hasNext()) {
	           c = (Car)it.next();
	           if(bestMPGCar!=null && c.compareMPG(bestMPGCar)>0) {
	               bestMPGCar=c;
	           }
	       }
	       return bestMPGCar;
	   }
	   public Car getCarWithHighestMileage() throws Exception{
	       Car highestMileageCar = this.get(0); Car c = null;
	       ListIterator<Car> it = this.listIterator();
	       while(it.hasNext()) {
	           c = (Car)it.next();
	           if(highestMileageCar!=null && c.compareMileage(highestMileageCar)>0) {
	               highestMileageCar=c;
	           }
	       }
	       return highestMileageCar;
	   }
	   public double getAverageMPG() throws Exception{
	       double averageMPG=0; double totalMPG=0; Car c=null;
	       ListIterator<Car> it = this.listIterator();
	       while(it.hasNext()) {
	           c = (Car)it.next();
	           totalMPG+=c.getMPG();
	       }
	       averageMPG=totalMPG/(this.size());
	       return averageMPG;
	   }
	   public double getTotalProfit() throws Exception {
	       double totalProfit = 0; Car c=null;
	       ListIterator<Car> it = this.listIterator();
	       while(it.hasNext()) {
	           c = (Car)it.next();
	           if(c.isSold()) {
	               totalProfit+=c.getProfit();
	           }
	       }
	       return totalProfit;
	   }
	        
			   


	public void loadFromDisk() throws IOException {
		try(BufferedReader br = new BufferedReader(new FileReader(file))) {
			String line = "";
			ArrayList<Car> Copy = new ArrayList<Car>();
	        while ((line = br.readLine()) != null) {
	        	String array[] = line.split(",", 0);
	        	String ID = array[0];
	        	int mileage = Integer.parseInt(array[1]);
	        	int MPG = Integer.parseInt(array[2]);
	        	Double cost = Double.parseDouble(array[3]);
	        	Double salesprice = Double.parseDouble(array[4]);
	        	Boolean sold = Boolean.parseBoolean(array[5]);
	        	Double pricesold = Double.parseDouble(array[6]);
	        	Double profit = Double.parseDouble(array[7]);
	    		Car c = new Car(ID, mileage, MPG, cost, salesprice);
	    		c.setSold(sold);
	    		c.setPriceSold(pricesold);
	    		c.setProfit(profit);
	    	    Copy.add(c);
	        }
	        this = Copy;
		}
		}

	public void saveToDisk() throws IOException {

		   FileWriter fw = new FileWriter(file);
	        for(int i=0;i<this.size();)
	        {
	        	 Car c = this.get(i);
	        	 fw.append(c.getID() + ",");
	        	 fw.append(c.getMileage() + ",");
	        	 fw.append(c.getMPG() + ",");
	        	 fw.append(c.getCost() + ",");
	        	 fw.append(c.getSalesPrice() + ",");
	        	 fw.append(c.isSold() + ",");
	        	 fw.append(c.getPriceSold() + ",");
	        	 fw.append(c.getProfit() + ",");
	        	 fw.append("\n");
	        	 i++;
	        }
	        fw.close();
	}

	}

Getting only two errors, one in SetInventory and one in loadfromDisk. Both refer to my use of "this" and say "The left hand side of an assignment must be a variable"

Mycroft Holmes
Mar 26, 2010

by Azathoth

ivantod posted:

Correct.

Sorry for not being 100% clear, but I was upset with the fact that the people who are supposed to be teaching the OP are telling them that is a good way to do things (e.g. by inheriting from ArrayList and stuff). The criticism was not intended against the OP, who I assume is doing their best to try to pass this class as is not at all to blame here for the stupid assignment they were given.

OP, I'm sorry, I absolutely was not indending to criticise you, sorry that it came across that way! I'm just angry at your teachers!

NP, didn't think you were insulting me.

ivantod
Mar 27, 2010

Mahalo, fuckers.

Mycroft Holmes posted:

Getting only two errors, one in SetInventory and one in loadfromDisk. Both refer to my use of "this" and say "The left hand side of an assignment must be a variable"

"This" is like a pointer to your current instance, so you can't assign a new value to "this" from within a class instance itself, because that would mean that you lose the reference to that current instance whose method is just now executing. But ArrayList has methods like clear and addAll which you can use to update the contents of "yourself". Possibly look into using one of both those in the places where you are trying to assign something to "this", which are giving you errors.

Mycroft Holmes
Mar 26, 2010

by Azathoth
Thanks for all the help, guys.

chippy
Aug 16, 2006

OK I DON'T GET IT

Mycroft Holmes posted:

Ok, here is the changed CarLot:

code:
	   public ArrayList<Car> getCarsInOrderOfEntry() {
	       ArrayList<Car> inventoryCopy = this;
	       return inventoryCopy;
	   }

You should know that this does not create a copy of the array. After doing this, the variable inventoryCopy is still pointing at the same array, not a copy of it. As it's written currently, this method is functionally identical to just
code:
return this;
Taking 'this' out of the equation (just in case it's causing some confusion), try doing something like this for yourself:

code:
ArrayList<Car> someCars = new ArrayList<>();

// some code to add 3 cars to someCars

ArrayList<Car> copyOfSomeCars = someCars;

// some code to add 2 cars to copyOfSomeCars

If you do this, and then iterate over both someCars and copyOfSomeCars, you will find that they both contain all 5 cars you added. This is because you only created one array, you just have two variables pointing to it. This is how variables which point to objects work in Java. The variables doesn't hold the object itself, but a reference to it. When you assign it to a new variable, that new variable gets a copy of the reference, not the object. That copy is still pointing to the same object.

chippy fucked around with this message at 18:43 on Dec 1, 2021

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

Paul MaudDib posted:

I can't figure out a way to programmatically configure a class as ControllerAdvice, only via the annotation.
It's still fine if you do this via the annotation on a regular class though? You could add something like @ConditionalOnMissingBean to only register it if someone else didn't already register an advice, or make it conditional on a configuration parameter, etc

Charles 2 of Spain
Nov 7, 2017

Any reason why you're using Double and Boolean instead of double and boolean in your loadFromDisk function?

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord
Is there an efficient way to parse large amounts of CSV data from an InputStream coming from AWS S3? I want to open a series of files, validate each line for formatting, and then merge them into a single file. Converting the stream into a BufferedReader and then performing evaluations the traditional way appears to be incredibly slow with a "small" file (~100MB) and the intent is for this to potentially run on 1+GB files. At this point all I'm doing is converting the data to lines and passing them to a multipart file upload and just the act of building the string to write is taking ages (like 10+ minutes without finishing).

Obviously S3 is going to be slower than a local filesystem, but unless I'm making a very big mistake (which is very possible!) this seems slow to me. In other jobs I have streamed 100+GB files, unzipped them in memory, and written the zip contents using raw bytearray streams and that only takes 45 mins or so which is much more in-line with what I was expecting.

Example:
partSize is a final long of 100MB. csvLines is a class StringBuilder variable so it can continue building between files before exceeding the filepart size limit. A final call of uploadStringStream() is made after all files have been parsed to complete any remaining lines as the final filepart.
Java code:
private void multiPartUploadSB(S3ObjectSummary source) throws IOException {
	S3Object object = s3.getObject(source.getBucketName(), source.getKey());
	InputStream is = object.getObjectContent();
	BufferedReader reader = new BufferedReader(new InputStreamReader(new BOMInputStream(is), StandardCharsets.UTF_8));
	if (skipHeader) {
		reader.readLine();
	}
	String line;
	while ((line = reader.readLine()) != null) {
		//validateCSVFormat(line);
		csvLines.append(line).append("\n");
		if (csvLines.toString.getBytes().length > partSize) {
			//This resets csvLines once completed
			uploadStringStream();
		}
	}
	reader.close();
	object.getObjectContent().abort();
	if (skipHeader) {
		skipHeader = true;
	}
}

Pedestrian Xing
Jul 19, 2007

Maybe experiment with a larger buffer size on your Reader? Default is 8kb which might be triggering a lot of new HTTP connections.

RandomBlue
Dec 30, 2012

hay guys!


Biscuit Hider

PierreTheMime posted:

Java code:
		if (csvLines.toString.getBytes().length > partSize) {

IIRC calling this repeatedly like this in a loop is very slow as it's converting the StringBuilder to a string, then to a byte array for every line you're processing in the input file. It'd be faster to get the size in bytes of each input line and increment a temp variable indicating how many bytes have been processed and then check to see if you're going to exceed your buffer size before adding more to the output.

Though the most likely culprit is the S3 transfer being slow. You might temporarily change the code so it loads that data into memory before any processing is done so you can separate the download from processing while trying to figure out why it's slow.

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord

RandomBlue posted:

IIRC calling this repeatedly like this in a loop is very slow as it's converting the StringBuilder to a string, then to a byte array for every line you're processing in the input file. It'd be faster to get the size in bytes of each input line and increment a temp variable indicating how many bytes have been processed and then check to see if you're going to exceed your buffer size before adding more to the output.
That is a very good point and what I had used in the other version, I'll go add that right now, thanks!

quote:

Though the most likely culprit is the S3 transfer being slow. You might temporarily change the code so it loads that data into memory before any processing is done so you can separate the download from processing while trying to figure out why it's slow.
I can do that as a first-pass check, but I won't be able to load excessively large files into memory. This is eventually going to be a Batch job living in AWS-land.

Edit: That absolutely was the issue. "calling this repeatedly like this in a loop is very slow" is an understatement of the century, the process runtime for 170MB of text is 43 seconds now.

PierreTheMime fucked around with this message at 18:04 on Dec 2, 2021

RandomBlue
Dec 30, 2012

hay guys!


Biscuit Hider

PierreTheMime posted:

Edit: That absolutely was the issue. "calling this repeatedly like this in a loop is very slow" is an understatement of the century, the process runtime for 170MB of text is 43 seconds now.

Yup, I've had to solve this exact problem before (without S3 being involved) and that was our core issue originally as well.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
Profiling the problematic code should reveal that sort of performance issue

Esran
Apr 28, 2008
Uh, so this isn't great.

https://twitter.com/dzikoysk/status/1469091718867951618

https://www.lunasec.io/docs/blog/log4j-zero-day/

If you don't disable the feature, log4j allows log statements like logger.info("some text") to contain placeholders which log4j will interpret. One of the placeholders allows you to invoke JNDI, which means you can get the logging system to try loading code from remote servers. This means attackers just have to get you to log some string they provide, and they can load code into your process.

Hippie Hedgehog
Feb 19, 2007

Ever cuddled a hedgehog?
Thanks! I was having some trouble parsing how exactly someone would use this to breach my system. So, basically like SQL injection, but they inject a templating string instead?

I guess there's no shortage of code that will log a string the user has submitted.

I guess there was a reason they were ordering people at the office to stay late on a Friday to bump library versions...

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

Hippie Hedgehog posted:

I guess there's no shortage of code that will log a string the user has submitted.
Yes, and think of all systems that log incoming request headers. The malicious payload could even be included in a User-Agent header.

CPColin
Sep 9, 2003

Big ol' smile.
"Relieved" to see that the various web applications we have that need to be rewritten because they're too old to upgrade are also too old to have the vulnerability. Never mind about whatever other vulnerabilities that suggests!

Hippie Hedgehog
Feb 19, 2007

Ever cuddled a hedgehog?

CPColin posted:

"Relieved" to see that the various web applications we have that need to be rewritten because they're too old to upgrade are also too old to have the vulnerability. Never mind about whatever other vulnerabilities that suggests!

Yeah, at my workplace, they officially consider "any version below 2.15.0" to be vulnerable. This particular jndi/ldap exploit I think only applies above .. .2.0.9-beta2? Or something. But apparently there are numerous other unpatched vulnerabilities in log4j 1.X, so...

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE

Hippie Hedgehog posted:

Yeah, at my workplace, they officially consider "any version below 2.15.0" to be vulnerable. This particular jndi/ldap exploit I think only applies above .. .2.0.9-beta2? Or something. But apparently there are numerous other unpatched vulnerabilities in log4j 1.X, so...

Oh, like what? We may need to upgrade at some point then.

Of course I’m sure our struts version is terribly vulnerable as well, they are so afraid of change they’ll never update.

Esran
Apr 28, 2008

Hippie Hedgehog posted:

Yeah, at my workplace, they officially consider "any version below 2.15.0" to be vulnerable. This particular jndi/ldap exploit I think only applies above .. .2.0.9-beta2? Or something. But apparently there are numerous other unpatched vulnerabilities in log4j 1.X, so...

The JNDI part was introduced in 2.0-beta9 (https://issues.apache.org/jira/browse/LOG4J2-313), so pretty much every 2.x version is vulnerable.

1.x is not vulnerable according to https://github.com/apache/logging-log4j2/pull/608#issuecomment-990494126, at least not in the same way, but see the discussion at https://github.com/apache/logging-log4j2/pull/608#issuecomment-991723301.

Regarding other vulnerabilities in 1.x, I'm only aware of these two https://snyk.io/vuln/maven%3Alog4j%3Alog4j.

ExcessBLarg!
Sep 1, 2001

Esran posted:

If you don't disable the feature, log4j allows log statements like logger.info("some text") to contain placeholders which log4j will interpret. One of the placeholders allows you to invoke JNDI, which means you can get the logging system to try loading code from remote servers.
That isn't exactly the problem. Like, this is always bad:
code:
log.info(untrusted);
whereas this is intended to be OK:
code:
log.info("User-passed data: {}", untrusted);
The problem is that in the latter example log4j still does property interpretation on the untrusted data. It should never do that. It should just take an arbitrary sequence of wide characters and mangle them however needs to be done to safely be printed to a log file.

Withnail
Feb 11, 2004
This seems like a colossal gently caress up by somebody. We have a bunch of legacy java web apps and I'm really really glad I moved out of that group.

CPColin
Sep 9, 2003

Big ol' smile.
It's probably a good thing I don't work in Security because every time one of these vulnerabilities comes to light I'm always like "so what?"

Esran
Apr 28, 2008

ExcessBLarg! posted:

That isn't exactly the problem. Like, this is always bad:
code:
log.info(untrusted);
whereas this is intended to be OK:
code:
log.info("User-passed data: {}", untrusted);
The problem is that in the latter example log4j still does property interpretation on the untrusted data. It should never do that. It should just take an arbitrary sequence of wide characters and mangle them however needs to be done to safely be printed to a log file.

That's true, but I don't think that's a very important distinction. As I understand it, only one component in Log4j (PatternAppender) even supports using lookups inside
code:
logger.info(untrusted)
I think the intent of
code:
logger.info("{}", arg)
wasn't to make logging more secure, it was to help Log4j avoid a bunch of string concatenation unless info-logging is enabled. I haven't seen anything in the documentation recommending the format-string form for security reasons at least.

Even if the format-string form didn't do property interpretation, it is still a gaping security hole in practice if a developer doing
code:
logger.info("hello " + world)
opens you up to injection where
code:
logger.info("hello {}", world)
doesn't. That would slip through review too easily I think. It would also be a problem for other JVM languages like Scala, where string interpolation exists as a language feature. People in that language will just do
code:
logger.info(s"hello $world")
and it would make log4j unusable there if doing that created a vulnerability for them.

I think from discussion on the mailing list, they are coming to the (IMO right) decision that allowing interpolation in logger input strings is too risky and does not provide much value, so they're removing that feature. Placeholders will only work in formats you specify in the logging config, which is much harder for an attacker to replace.

Esran fucked around with this message at 20:00 on Dec 13, 2021

jiffypop45
Dec 30, 2011

I haven't touched Java since 1.6 (2012-ish?) and need to relearn it for my job, I have prior dev experience but need a recommendation for a book, I would prefer one that has exercises at the end of chapters to work through. Does anyone have a plug for one they like? I usually do no-starch but theirs doesn't seem super great for what I'm trying to do since its just walking you through projects.

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE

Esran posted:

I think from discussion on the mailing list, they are coming to the (IMO right) decision that allowing interpolation in logger input strings is too risky and does not provide much value, so they're removing that feature. Placeholders will only work in formats you specify in the logging config, which is much harder for an attacker to replace.

yeah this is my interpretation too, it should have been fine to allow runtime-configured convenience features (although loading arbitrary class loading is a step too far imo) via the config files but they’re actually scanning the string for those tokens after the log input string is generated, which obviously opens up logging injection attacks.

Even from a performance sense, you really want to follow the model where the logger is built once at startup and allowing runtime log strings to load additional things after logger initialization is kind of baffling and potentially opens up resource leaks/etc.

Esran
Apr 28, 2008
Yes, agreed about loading arbitrary classes. The problem is that JNDI is a really powerful tool with an innocent-looking interface. The code in log4j2 basically just looks like this:
code:
InitialContext ctx = new InitialContext();
ctx.lookup(jndiName)
The guy who added it said he needed it to look up which application in an application server (e.g. Tomcat) the logs were coming from (it used to be common to run many applications in the same JVM), which is exposed via JNDI. Unless you know in advance that JNDI can do wild poo poo like loading code from other servers if you pass it the wrong name, I can see how this code could make it past review unscathed.

ExcessBLarg!
Sep 1, 2001

Esran posted:

That's true, but I don't think that's a very important distinction. As I understand it, only one component in Log4j (PatternAppender) even supports using lookups inside
code:
logger.info(untrusted)
I think the intent of
code:
logger.info("{}", arg)
wasn't to make logging more secure, it was to help Log4j avoid a bunch of string concatenation unless info-logging is enabled. I haven't seen anything in the documentation recommending the format-string form for security reasons at least.
I've only used SLF4J, not Log4j, but the interpolation interface seemed so obviously modeled after format strings or prepared statements that it never occurred to me that it wasn't for security reasons.

Esran
Apr 28, 2008
I think it came as a surprise to everyone (including some of the log4j devs lol :v:) that there would even be a security reason to use the interpolation form, since I don't think many people were aware that you could do placeholders in log messages in the first place.

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE
https://www.lunasec.io/docs/blog/log4j-zero-day-update-on-cve-2021-45046/

log4j2 electric boogaloo: i warned u about jndi bro!



also guess what’s apparently a giant Java legacy monolith? SMS backend systems, lol. Makes sense, SIM cards are all Javacard - and the easiest way to interop with that is probably more Java. It all runs Java!

https://mobile.twitter.com/infosecatom/status/1469774771634249740?s=21

Paul MaudDib fucked around with this message at 10:49 on Dec 15, 2021

Sir Lemming
Jan 27, 2009

It's a piece of JUNK!
Thought I was being overly cautious when I wrote "upgrade to 2.15.0 (or higher, if available)" in my recommendations, but I guess not, lol.

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE
Is there a notional problem with serving an api of {serviceName, apiVersion, gitCommitShortHash, gitCommitTime}?

serviceName and apiVersion are practically public info. gitCommit tells you when it was built and what the short hash was.

Like, I dunno if I'd make the commit info public willingly, but it's kinda important internally for tracking builds/changes. Short commit does give you a unique handle into some git tree presumably, but there's also likely many strings that could uniquely identify your code...

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE
oh gently caress, how many android things use log4j2?

AT&T just cut off both my parents Samsung J7s. Can't talk to the network anymore, cut off, "please call us we're giving you a free S9!", my iphone on the plan is fine. I wonder if that was a log4j thing.

What if Android can be pwned by SMS or some other basic vuln?

7 billion devices run java. (tm) Especially a lot of Javacard infra and baseband infra, apparently.

Paul MaudDib fucked around with this message at 14:08 on Dec 16, 2021

necrotic
Aug 2, 2005
I owe my brother big time for this!

Paul MaudDib posted:

Is there a notional problem with serving an api of {serviceName, apiVersion, gitCommitShortHash, gitCommitTime}?

serviceName and apiVersion are practically public info. gitCommit tells you when it was built and what the short hash was.

Like, I dunno if I'd make the commit info public willingly, but it's kinda important internally for tracking builds/changes. Short commit does give you a unique handle into some git tree presumably, but there's also likely many strings that could uniquely identify your code...

A git short hash might as well be a random identifier. It is not enough to do anything with outside of identify the version. If they could use that git sha it means they have your repo and exposing that sha doesn’t matter at that point.

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE

necrotic posted:

A git short hash might as well be a random identifier. It is not enough to do anything with outside of identify the version. If they could use that git sha it means they have your repo and exposing that sha doesn’t matter at that point.

the idea I don't like is giving a publicly servable hash that could be used to trivially aim and target the git repo on the network. Yes, if they can find it, they could target other strings, and it's not supposed to be available at all, but a commit hash (short or full) is more or less an arrow back to git and potentially any credentials that are stored there/etc.

yes, if they have the hash and access they win, but, at least it's not literally "scan for hash files in .git with this substring".

necrotic
Aug 2, 2005
I owe my brother big time for this!

Paul MaudDib posted:

the idea I don't like is giving a publicly servable hash that could be used to trivially aim and target the git repo on the network. Yes, if they can find it, they could target other strings, and it's not supposed to be available at all, but a commit hash (short or full) is more or less an arrow back to git and potentially any credentials that are stored there/etc.

yes, if they have the hash and access they win, but, at least it's not literally "scan for hash files in .git with this substring".

If they have your git repo they will find what they want in it, regardless of having the short hash exposed in some public identifier or not. Also, don’t store credentials in the repo. They should exist outside the repo so if the repo is popped they don’t get credentials.

Hippie Hedgehog
Feb 19, 2007

Ever cuddled a hedgehog?

Paul MaudDib posted:

oh gently caress, how many android things use log4j2?

AT&T just cut off both my parents Samsung J7s. Can't talk to the network anymore, cut off, "please call us we're giving you a free S9!", my iphone on the plan is fine. I wonder if that was a log4j thing.

What if Android can be pwned by SMS or some other basic vuln?

7 billion devices run java. (tm) Especially a lot of Javacard infra and baseband infra, apparently.

Yes everything runs Java, but not everything runs Log4j2, fortunately. I bet the J7s do, just like you guess. I wouldn't want them on my network, either.

Bedlam
Feb 15, 2008

Angry thoughts

I'm relatively new to JAVA so I hope this isn't too silly of a question but I'm having an issue with my project that I feel like is simple but my google searches haven't helped.

I'm using Spring Tool Suite and I'm making a review website where things can be rated 0-5 stars. This is stored in my model attribute for the review as the Rating property, that is 0 - 5. I'm trying to create a for loop in my jsp that takes the value of that model attribute (0 - 5) and loops that many times, each time populating a Star on the html. I have the star from fontawesome, my model attribute works fine and the data is passing fine, but I don't know how to make the loop... create html on the jsp.

Am I overthinking this and is there a simple way to do this? I'm not very familiar with JSP's and i'm kinda flying the seat of my pants on this one.

Adbot
ADBOT LOVES YOU

Guildenstern Mother
Mar 31, 2010

Why walk when you can ride?
I'm pretty new as well, but I'd use thymeleaf, pretty simple to add the dependency in spring and it makes it very easy to do exactly what you're wanting to do with the th:each tag.
https://www.baeldung.com/thymeleaf-iteration

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply