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
Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Below code help you get database backup simple
____________________/

Adbot
ADBOT LOVES YOU

abiogenesis
Feb 4, 2009

Monkeyseesaw posted:

This is largely moot anyway. He's not writing unit tests for a drat school assignment.

I ended up overloading the method and doing both.

code:
public void register(Scanner scan) {

     /* take in keyboard stuff,
      *  store to vars
      */

     register(name, number);

}

public void register(String name, int num) {

     /* do whatever she wanted originally */

}
As far as horrors go, her husband has a requirement that we write methods that are no longer than 10 lines and have ABSOLUTELY NO nested loops. This leads to extraneous method calls and methods that complete smaller loops inside of big ones. :saddowns:

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

abiogenesis posted:

I ended up overloading the method and doing both.

code:
public void register(Scanner scan) {

     /* take in keyboard stuff,
      *  store to vars
      */

     register(name, number);

}

public void register(String name, int num) {

     /* do whatever she wanted originally */

}
As far as horrors go, her husband has a requirement that we write methods that are no longer than 10 lines and have ABSOLUTELY NO nested loops. This leads to extraneous method calls and methods that complete smaller loops inside of big ones. :saddowns:

I'm not really sure those qualify as horrors per se. Good coding practices taken to their extreme, sure, but when dealing with students you can't expect them to understand the difference between a 30-line method that really just needs to be 30 lines and a 30 line method that needs to be broken into pieces.

spiritual bypass
Feb 19, 2008

Grimey Drawer

Ryouga Inverse posted:

I'm not really sure those qualify as horrors per se. Good coding practices taken to their extreme, sure, but when dealing with students you can't expect them to understand the difference between a 30-line method that really just needs to be 30 lines and a 30 line method that needs to be broken into pieces.

Seriously?

When I was in school it seemed that every CS major knew without being told to make a function when you're going to re-use the same code in several places. Doing it arbitrarily is just confusing and stupid.

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

rt4 posted:

Seriously?

When I was in school it seemed that every CS major knew without being told to make a function when you're going to re-use the same code in several places. Doing it arbitrarily is just confusing and stupid.

You must have gone to a pretty high-grade school, then, because I work with CS grads that think copypasta is a valid development strategy.

HFX
Nov 29, 2004

abiogenesis posted:

I ended up overloading the method and doing both.

code:
public void register(Scanner scan) {

     /* take in keyboard stuff,
      *  store to vars
      */

     register(name, number);

}

public void register(String name, int num) {

     /* do whatever she wanted originally */

}
As far as horrors go, her husband has a requirement that we write methods that are no longer than 10 lines and have ABSOLUTELY NO nested loops. This leads to extraneous method calls and methods that complete smaller loops inside of big ones. :saddowns:

This requirement is actually very good as long as the functions are doing small things. Calling functions isn't just about code reuse. They are also for defining simple concise behaviors/operations. If it is a coding horror, then I am a coding horror since I don't tend to write more then 5-10 lines in a function without breaking it down (declarations or exception catching are an exception).
They also make more sense once you learn a functional languages or languages which allow functional like operations

Edit: I added the concise behaviors part and the part of where you should learn this.
Edit 2: You'll wish everyone used such a rule when on the first project you get assigned to is to maintain your coworkers code who believed in copy/paste and 50+ line functions.

HFX fucked around with this message at 04:03 on Apr 20, 2010

ColdPie
Jun 9, 2006

HFX posted:

This requirement is actually very good as long as the functions are doing small things. Calling functions isn't just about code reuse. They are also for defining simple concise behaviors/operations. If it is a coding horror, then I am a coding horror since I don't tend to write more then 5-10 lines in a function without breaking it down.

Obviously the problem is having overly strict rules with no room for exceptions. It's fine as a general guideline, not as a hard and fast rule that everyone must follow at all times.

HFX
Nov 29, 2004

ColdPie posted:

Obviously the problem is having overly strict rules with no room for exceptions. It's fine as a general guideline, not as a hard and fast rule that everyone must follow at all times.

However, for most students if you give them a chance to ignore the rule, they will do it constantly.

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

HFX posted:

However, for most students if you give them a chance to ignore the rule, they will do it constantly.

Yes, it's exactly like goto. Students have not yet learned the judgment necessary to determine when breaking the rules is warranted.

shrughes
Oct 11, 2008

(call/cc call/cc)
I saw this today:

code:
static enum ParseState consume(NSMutableData *output, const char **posRef, const char *end, enum
 ParseState state, NSString **lastSeenThreadId) {
	const char *pos = *posRef;
	const char *r = pos;
more:
	switch (state) {
		case ParseStateTop: {
			const char *linkBeg = skipThroughSegment(&r, end,
 "<link rel=\"stylesheet\"" "type=\"text/css\" href=\"http://ycombinator.com/news.css\">");
			if (!linkBeg) {
				break;
			}
			state = ParseStateBeforeScript;
			[output appendBytes:pos length:linkBeg - pos];
			static const char alternateLink[] = "<link rel=\"stylesheet\" type=\"text/"
"css\" href=\"hn://ycombinator.com/news.css\">";
			[output appendBytes:alternateLink length:strlen(alternateLink)];
			pos = r;
			NSLog(@"Modified stylesheet!");
		}
			// fallthru
		case ParseStateBeforeScript: {
			if (!skipThroughString(&r, end, "var item = v[1];")) {
				break;
			}
			state = ParseStateBeforeMainTable;
			[output appendBytes:pos length:r - pos];
			pos = r;
			static const char confirmation[] = "if (!confirm('Sure you want to vote '"
" + v[0] + '?')) { return false; }";
			[output appendBytes:confirmation length:strlen(confirmation)];
		}
			// fallthru
		case ParseStateBeforeMainTable: {
			const char *attrBeg = NULL;
			const char *attrEnd = NULL;
			const char *segBeg = skipThroughTagWithAttr(&r, end, "table",
 "width=\"85%\"", &attrBeg, &attrEnd);
			if (!segBeg) {
				break;
			}
			state = ParseStateBeforePageTop;
			[output appendBytes:pos length:attrBeg - pos];
			static const char fullWidth[] = kFullTableWidth;
			[output appendBytes:fullWidth length:strlen(fullWidth)];
			[output appendBytes:attrEnd length:r-attrEnd];
			pos = r;
			NSLog(@"Full width!");
		}
			// fallthru
		case ParseStateBeforePageTop: {
			BOOL through = NULL != skipThroughSegment(&r, end,
 "<span class=\"pagetop\">");
			if (!through) {
				break;
			}
			state = ParseStateAfterPageTop;
			NSLog(@"Pierced through pagetop!");
		}
			// fallthru
		case ParseStateAfterPageTop: {
			BOOL through = NULL != skipThroughCloser(&r, end, "table");
			if (!through) {
				break;
			}
			state = ParseStateAfterTopRow;
			NSLog(@"Pierced through top row!");
		}
			// fallthru
		case ParseStateAfterTopRow: {
			BOOL through = NULL != skipThroughOpeningTag(&r, end, "table");
			if (!through) {
				break;
			}
			state = ParseStateInContentTable;
			NSLog(@"In content table!");
		}
			// fallthru
		case ParseStateInContentTable: {
			const char *attrBeg;
			const char *attrEnd;
			BOOL isDefault;
			const char *opener = choiceTagWithAttr(&r, end, "td", "class=\"default\"",
 "class=\"title\"", &attrBeg, &attrEnd, &isDefault);
			if (!opener) {
				break;
			}
			if (isDefault) {
				const char *tdDefault = opener;
				const char *commentWalker = r;
				r = tdDefault;
				const char *tdDefaultClassInsertionPoint = attrEnd - 1;
				const char *spanComhead = skipThroughTagWithAttr(&commentWalker,
 end, "span", "class=\"comhead\"", &attrBeg, &attrEnd);
				if (!spanComhead) {
					break;
				}
				if (!skipThroughTagWithAttr(&commentWalker, end, "span",
 "id=score_", &attrBeg, &attrEnd)) {
					break;
				}
				const char *beginningOfCommentId = attrEnd;
				const char *endOfCommentId = eatToChar(beginningOfCommentId,
 end, '>');
				if (!skipThroughTagWithAttr(&commentWalker, end, "span",
 "class=\"comment\"", &attrBeg, &attrEnd)) {
					break;
				}
	//			const char *beginningOfComment = commentWalker;
				const char *endOfComment = skipThroughCloser(&commentWalker,
 end, "span");
				// If we haven't read the whole comment, move r before 
// the recognizable td class="default".
				if (endOfComment == NULL) {
					break;
				}
				NSString *itemId = [NSString stringWithCString:beginningOfCommentId
 length:endOfCommentId - beginningOfCommentId];
				NSString *threadId = *lastSeenThreadId;
				enum PostTrackerPostNovelty novelty = threadId ? [[PostTracker
 thePostTracker] noticePost:itemId inThread:threadId] : PostTrackerPostNoveltyNotNew;

				// alright.  let's write.
				// Write data up to td class="default":
				[output appendBytes:pos length:tdDefaultClassInsertionPoint - pos];
				// Adjust td class:
				const char *extraClass = novelty == PostTrackerPostNoveltyNew ?
 " noveltyNew" : "";
				[output appendBytes:extraClass length:strlen(extraClass)];
				// write everything else consumed:
				[output appendBytes:tdDefaultClassInsertionPoint length:
commentWalker - tdDefaultClassInsertionPoint];
				pos = commentWalker;
				r = pos;
			} else {
				const char *tdTitle = opener;
				const char *titleWalker = r;
				r = tdTitle;
				if (!skipThroughTagWithAttr(&titleWalker, end, "span",
 "id=score_", &attrBeg, &attrEnd)) {
					break;
				}
				const char *beginningOfThreadId = attrEnd;
				const char *endOfThreadId = eatToChar(beginningOfThreadId,
 end, '>');
				if (!skipThroughTagWithAttr(&titleWalker, end, "a",
 "href=\"item?id=", &attrBeg, &attrEnd)) {
					break;
				}
				const char *beginningOfCommentCount = titleWalker;
				const char *endOfCommentCount = eatToOneOf(beginningOfCommentCount,
 end, " <");
				titleWalker = eatToChar(titleWalker, end, '<');
				if (!titleWalker) {
					break;
				}
				// Now, how many comments do we have, and what's our thread id?
				NSString *commentCountString = [NSString 
stringWithCString:beginningOfCommentCount length:endOfCommentCount - beginningOfCommentCount];
				NSInteger commentCount = [commentCountString integerValue];
				NSString *threadId = [NSString stringWithCString:
beginningOfThreadId length:endOfThreadId - beginningOfThreadId];
				NSLog(@"Comment count string: %@ thread id string: %@", 
commentCountString, threadId);
				NSInteger knownComments = [[PostTracker thePostTracker] 
knownCommentsForThread:threadId];
				// now for some output...
				[output appendBytes:pos length:titleWalker - pos];
				if (commentCount > knownComments) {
					NSString *s = [NSString stringWithFormat:@" <b>(%d)</b>", 
(commentCount - knownComments)];
					[output appendData:
[s dataUsingEncoding:NSASCIIStringEncoding]];
				}
				pos = titleWalker;
				r = pos;
				*lastSeenThreadId = [threadId retain];
			}
		}
			goto more;
		default:
			r = end;
			break;
	}
	[output appendBytes:pos length:r - pos];
	*posRef = r;
	return state;
}
A gigantic switch statement? Check. Switches with fallthrough? Check. Goto statements? Check. Intermingling patterns for altering external state? Check. The use of retain in the middle of nowhere? Check. Haphazard mechanisms for holding up a stream? Check. Extreme parsing fragility? Check. A haphazard mix of hardcoded strings and references to preprocessor defines? Check. Useless variable names? Check. I wrote it myself.

Edit: added hardwrapping to be less annoying

shrughes fucked around with this message at 05:42 on Apr 20, 2010

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...
The best coding horrors are the ones you yourself implement. Especially when you know you're implementing a coding horror as you do it.

evensevenone
May 12, 2001
Glass is a solid.
This is probably a horror, right?

code:
void makeUpperCase(string& word)
{
	if (word != "")
	{
		if (word[0] >= 'a' and word[0] <= 'z')
		{
			word[0] = word[0] - 32;
			
		}
		string sub = word.substr(1);	
		makeUpperCase(sub);
		word = word[0] + sub;
	}
}

UraniumAnchor
May 21, 2006

Not a walrus.
Clearly somebody decided recursion was the BEST THING EVER.

Bozart
Oct 28, 2006

Give me the finger.

evensevenone posted:

This is probably a horror, right?

code:
void makeUpperCase(string& word)
...
}

Someone read the first few pages of the little schemer and decided to try something harder?

Dr Monkeysee
Oct 11, 2002

just a fox like a hundred thousand others
Nap Ghost

Plorkyeran posted:

Why? I wrote unit tests for nearly every school assignment I did.

Things have changed since I was in school. To be fair unit tests were some weird obscure thing the Smalltalk community was pushing at the time.

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

code:
string makeUpperCase(string& word)
{
	return makeUpperCaseHelper(word, 0);
}

string makeUpperCaseHelper(string& word, int i)
{
	if (i == strlen(word)) return;

	if (word[i] >= 'a' and word[i] <= 'z')
	{
		word[i] = word[i] - 32;
	}

	return makeUpperCase(word, i + 1);
}
There, I fixed the problem - I added an accumulator so it's now tail-recursive :pseudo:

PrBacterio
Jul 19, 2000

Dijkstracula posted:

code:
string makeUpperCase(string& word)
{
	return makeUpperCaseHelper(word, 0);
}

string makeUpperCaseHelper(string& word, int i)
{
	if (i == strlen(word)) return;

	if (word[i] >= 'a' and word[i] <= 'z')
	{
		word[i] = word[i] - 32;
	}

	return makeUpperCase(word, i + 1);
}
There, I fixed the problem - I added an accumulator so it's now tail-recursive :pseudo:
Now if only the C++ compiler optimized tail calls not to use any stack space :eng99:

king_kilr
May 25, 2007

PrBacterio posted:

Now if only the C++ compiler optimized tail calls not to use any stack space :eng99:

Uhh, most do.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip

king_kilr posted:

Uhh, most do.

You sure about this? Last I heard C and C++ compilers were generally "loving terrible" at tco and trampolining

POKEMAN SAM
Jul 8, 2004

Otto Skorzeny posted:

You sure about this? Last I heard C and C++ compilers were generally "loving terrible" at tco and trampolining

http://www.linux-kongress.org/2009/slides/compiler_survey_felix_von_leitner.pdf posted:

gcc has removed tail recursion for years. icc, suncc and msvc don’t.

Vinterstum
Jul 30, 2003

Ugg boots posted:

http://www.linux-kongress.org/2009/slides/compiler_survey_felix_von_leitner.pdf posted:

gcc has removed tail recursion for years. icc, suncc and msvc don’t.

That paper talks about C, though. I'd imagine the situation would be pretty different in C++ when you have objects on the stack that needs destruction.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
I wondered whether clang would perform TCO, and was pleasantly surprised:

The LLVM Docs posted:

Tail call optimization

Tail call optimization, callee reusing the stack of the caller, is currently supported on x86/x86-64 and PowerPC. It is performed if:
  • Caller and callee have the calling convention fastcc or cc 10 (GHC call convention).
  • The call is a tail call - in tail position (ret immediately follows call and ret uses value of call or is void).
  • Option -tailcallopt is enabled.
  • Platform specific constraints are met.

x86/x86-64 constraints:
  • No variable argument lists are used.
  • On x86-64 when generating GOT/PIC code only module-local calls (visibility = hidden or protected) are supported.

PowerPC constraints:
  • No variable argument lists are used.
  • No byval parameters are used.
  • On ppc32/64 GOT/PIC only module-local calls (visibility = hidden or protected) are supported

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
LLVM actually does two kinds of TCO: an IR-level optimization which rewrites recursive tail calls into loops, and a machine-level optimization which turns tail calls into jumps. That page is only talking about the latter; the former is target-independent and done at -O1 and higher.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Exxxxxtreeeeeeme MUMPS!

Zhentar
Sep 28, 2003

Brilliant Master Genius
:smith:

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Mustach posted:

Exxxxxtreeeeeeme MUMPS!



Example challenge: Convince your coworkers that the following is not an appropriate response to "I found a security vulnerability that allows a user to execute arbitrary code on the database server":

quote:

This is a known issue. There are few ways to avoid this:

1. Use BulkRPC for sending user entered data.
2. Or, make sure you wrap the user entered data in quotes (properly) before sending it to the server using RPC.

Also this problem is not isolated to how we do calls to the database server. It's industry wide problem. You can create havoc using SQL injections if the user entered data is not properly validated.

evensevenone
May 12, 2001
Glass is a solid.
Shouldn't you be cleaning the input as close to where it gets input as possible? Not right before it gets to the database?

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."

evensevenone posted:

Shouldn't you be cleaning the input as close to where it gets input as possible? Not right before it gets to the database?

If you sanitize input on a client application but not at the server layer, you're only going to prevent honest mistakes. It doesn't hurt to sanity check on several layers, but anything that touches the database is the most important link in the chain.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Basically the library required you to know its internal implementation in order to be safe, since you called it like
code:
arg1 = "foo"
arg2 = 1
arg3 = "I'll kill you\"); evilevilevil() #"
DoSomething("func", arg1, arg2, arg3)
which got turned into some code on the server like
code:
func("foo", "1", "I'll kill you"); evilevilevil() #")
with no indication in any of the documentation that that's how it actually worked. The whole point of abstracting out that layer is to automatically handle escaping strings properly (see basically any SQL library's execute() function). It is not the responsibility of the input reader to know how to escape strings to prevent injection attacks (unless you are a fan of the cut-n-paste pattern).

Avenging Dentist fucked around with this message at 01:34 on Apr 21, 2010

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

evensevenone posted:

Shouldn't you be cleaning the input as close to where it gets input as possible? Not right before it gets to the database?
There's a difference between invalid input and input that has to be escaped. "gently caress you" in a phone number field should probably be rejected by the UI, but "O'Connor" in a name field certainly shouldn't be rejected. It might need to be escaped prior to being sent to the database, but that should be handled by the code that actually calls the database, not some higher level module.

king_kilr
May 25, 2007

Plorkyeran posted:

There's a difference between invalid input and input that has to be escaped. "gently caress you" in a phone number field should probably be rejected by the UI, but "O'Connor" in a name field certainly shouldn't be rejected. It might need to be escaped prior to being sent to the database, but that should be handled by the code that actually calls the database, not some higher level module.

Sanitizing DB inputs is a coding horror. Prepared statements guys, or are you all 12 year old PHP script kiddies.

Zhentar
Sep 28, 2003

Brilliant Master Genius

Plorkyeran posted:

There's a difference between invalid input and input that has to be escaped. "gently caress you" in a phone number field should probably be rejected by the UI, but "O'Connor" in a name field certainly shouldn't be rejected. It might need to be escaped prior to being sent to the database, but that should be handled by the code that actually calls the database, not some higher level module.

There's also the small matter of free text comment fields, where there essentially is no invalid input; someone can enter "Comment' DROP TABLE TRANSACTIONS" if they want to, and there shouldn't be anything wrong with that.

Edit:

Avenging Dentist posted:

with no indication in any of the documentation that that's how it actually worked.
To be fair, there probably wasn't any documentation to indicate it.

Zhentar fucked around with this message at 02:35 on Apr 21, 2010

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

king_kilr posted:

Sanitizing DB inputs is a coding horror. Prepared statements guys, or are you all 12 year old PHP script kiddies.
Obviously if you're communicating with the database in a sane way this entire topic never comes up. One part of your system being awful is no excuse for giving up everything else, though. I'm pretty sure prepared statements were not an option in AD's case.

spiritual bypass
Feb 19, 2008

Grimey Drawer

king_kilr posted:

Sanitizing DB inputs is a coding horror. Prepared statements guys, or are you all 12 year old PHP script kiddies.

Yes but you see the mysql() functions are so fast and those database libraries are so bloated and I am designing my application for speed and I am a genius and I will ignore all of your suggestions and/or build my own DB library

Hey guys I don't understand why this nested loop is taking so long

ih8ualot
May 20, 2004
I like turkey and ham sandwiches

Ryouga Inverse posted:

The best coding horrors are the ones you yourself implement. Especially when you know you're implementing a coding horror as you do it.

Case in point.
code:
function setFrustumCorners(TL, TR, BR, BL){
	// I'm...I'm so sorry.
	topLeft = BL;
	topRight = BR;
	botRight = TR;
	botLeft = TL;
	
	
}
It's been fixed, but I always keep a copy to remind myself how loving retarded my code is sometimes.

GROVER CURES HOUSE
Aug 26, 2007

Go on...
Code that actually apologizes for existing is the cutest thing ever. :3:

Until you have to do something about it, then it's like taking a kitten out the back with a shotgun. :smithicide:

PhonyMcRingRing
Jun 6, 2002
I have a friend that has been using the same SQL class he made for .Net for years. I feel dirty having used it, but I was a brand new programmer and didn't know any better at the time.

Basically, in order to prevent SQL injections, he does the following for string values:

-Replaces " with "
-Replaces ? with &quest
-Replaces ' with &apost

And then he has to replace those back and forth each time.

He does this for all strings, not just encoding html strings or something(which wouldn't work anyway since he doesn't use the correct format).

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

rt4 posted:

Yes but you see the mysql() functions are so fast and those database libraries are so bloated and I am designing my application for speed and I am a genius and I will ignore all of your suggestions and/or build my own DB library

Hey guys I don't understand why this nested loop is taking so long
If I was designing my a DB library then I wouldn't let it put parameters directly in the code anyway.

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

PhonyMcRingRing posted:

-Replaces " with "
This made me smile :v:

Adbot
ADBOT LOVES YOU

Crazy RRRussian
Mar 5, 2010

by Fistgrrl
Isn't the only thing you need to do to prevent SQL injection is to just use compiled statements?

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