def explain_asan_error(loc, output_stream, color): if loc: print("%s:%d" % (loc.filename, loc.line_number), end=' ', file=output_stream) report = os.environ.get('DCC_ASAN_ERROR') if report: report = report.replace('-', ' ') report = report.replace('heap', 'malloc') report = report.replace('null deref', 'NULL pointer dereferenced') else: report = "illegal array, pointer or other operation" print('runtime error -', color(report, 'red'), file=output_stream) prefix = '\n' + color('dcc explanation:', 'cyan') if "malloc buffer overflow" in report: print(prefix, """access past the end of malloc'ed memory. Make sure you have allocated enough memory for the size of your struct/array. A common error is to use the size of a pointer instead of the size of the struct or array. """, file=output_stream) print('For more information see:', explanation_url('malloc_sizeof'), file=output_stream) if "stack buffer overflow" in report: print(prefix, """access past the end of a local variable. Make sure the size of your array is correct. Make sure your array indices are correct. """, file=output_stream) elif "use after return" in report: print( prefix, """You have used a pointer to a local variable that no longer exists. When a function returns its local variables are destroyed. """, file=output_stream) print('For more information see:', explanation_url('stack_use_after_return'), file=output_stream) elif "use after" in report: print(prefix, "access to memory that has already been freed.\n", file=output_stream) elif "double free" in report: print(prefix, "attempt to free memory that has already been freed.\n", file=output_stream) elif "null" in report.lower(): print(prefix, "attempt to access value using a pointer which is NULL.\n", file=output_stream)
def get(self, message, colorize_output): explanation = self.get_short_explanation(message, colorize_output) if explanation and (self.long_explanation or self.long_explanation_url): url = self.long_explanation_url or explanation_url(self.label) explanation += "\n See more information here: " + url return explanation
def check_bad_characters(line, line_number, danger, expected): if re.search(rb'[\x00-\x08\x14-\x1f\x7f-\xff]', expected): return None m = re.search(rb'^(.*?)([\x00-\x08\x14-\x1f\x7f-\xff])', line) if not m: return None (prefix, offending_char) = m.groups() offending_value = ord(offending_char) if offending_value == 0: description = "zero byte ('" + danger('\\0') + "')" elif offending_value > 127: description = "non-ascii byte " + danger("\\x%02x" % (offending_value)) else: description = "non-printable character " + danger("\\x%02x" % (offending_value)) column = len(prefix) explanation = "a " + danger("non-ASCII byte") + " was printed.\n" explanation += "Byte %d of line %d of program output was a %s\n" % ( column + 1, line_number, description) explanation += "Here is line %d with non-printable characters replaced with backslash-escaped equivalents:\n" % ( line_number) line = repr(line)[2:-1] + '\n' line = re.sub(r'(\\x[0-9a-f][0-9a-f])', danger(r'\1'), line) explanation += line if offending_value == 255: explanation += "\nHave you accidentally printed the special EOF value getchar returns?\n" explanation += "For more information go to: " + explanation_url( "eof_byte") + "\n" return explanation
def explain_output_difference1(loc, output_stream, color): # values supplied for expected output for this execution expected_stdout = os.environb.get(b'DCC_EXPECTED_STDOUT', '') # ignore_case = getenv_boolean('DCC_IGNORE_CASE') # ignore_empty_lines = getenv_boolean('DCC_IGNORE_EMPTY_LINES') ignore_trailing_white_space = getenv_boolean( 'DCC_IGNORE_TRAILING_WHITE_SPACE', default=True) # compare_only_characters = os.environ.get('DCC_COMPARE_ONLY_CHARACTERS') # value describing discrepency between actual and expected output reason = os.environ.get('DCC_OUTPUT_ERROR', '') line_number = getenv_int('DCC_ACTUAL_LINE_NUMBER') # these values do not include current line n_expected_bytes_seen = getenv_int('DCC_N_EXPECTED_BYTES_SEEN') n_actual_bytes_seen = getenv_int('DCC_N_ACTUAL_BYTES_SEEN') expected_line = os.environb.get(b'DCC_EXPECTED_LINE', '') actual_line = os.environb.get(b'DCC_ACTUAL_LINE', '') expected_column = getenv_int('DCC_EXPECTED_COLUMN') actual_column = getenv_int('DCC_ACTUAL_COLUMN') if 0 <= actual_column < len(actual_line): actual_char = actual_line[actual_column] else: actual_char = None if ignore_trailing_white_space and expected_stdout[-1:] == b'\n': expected_stdout = expected_stdout.rstrip() + b'\n' n_expected_lines = len(expected_stdout.splitlines()) is_last_expected_line = n_expected_bytes_seen + len(expected_line) >= len( expected_stdout) if 0 <= expected_column < len(expected_line): expected_byte = expected_line[expected_column:expected_column + 1] else: expected_byte = None # primary = lambda text, **kwargs: color(text, style='bold', **kwargs) danger = lambda text, **kwargs: color( text, fg='red', style='bold', **kwargs) success = lambda text, **kwargs: color( text, fg='green', style='bold', **kwargs) # info = lambda text, **kwargs: color(text, fg='cyan', style='bold', **kwargs) if not actual_line.endswith(b"\n"): print("Execution failed because ", end='', file=output_stream) else: print("Execution stopped because ", end='', file=output_stream) if reason == "expected line too long": print("internal error: expected line too long", file=output_stream) return if reason == "line too long": print("program wrote", danger("a line containing over " + str(actual_column) + " bytes."), file=output_stream) print("Do you have an infinite loop?", file=output_stream) print_line(actual_line, "start of the", danger, output_stream) return if reason == "too much output": print("program produced", danger("too much output."), file=output_stream) print("Your program printed", actual_column, "bytes.") print("Do you have an infinite loop?", file=output_stream) print_line(actual_line, "last", danger, output_stream) return if reason == "zero byte": print("a", danger("zero byte ('\\0')"), "was printed.", file=output_stream) print("Byte", actual_column, "of line", line_number, "of program's output was a zero byte ('\\0')", file=output_stream) if len(expected_line): print("Here are the characters on the line before the zero byte:", file=output_stream) print(sanitize(actual_line), file=output_stream) print("\nFor more information go to:", explanation_url("zero_byte"), file=output_stream) return if n_actual_bytes_seen == 0 and len(actual_line) == 0: print("program produced", danger("no output."), file=output_stream) print(n_expected_lines, "lines of output were expected", file=output_stream) print_line(expected_line, "first expected", success, output_stream) return if len(actual_line) == 0: print("of", danger("missing output lines."), file=output_stream) print( "Your program printed", line_number, "lines of correct output but stopped before printing all the expected output.", file=output_stream) print_line(expected_line, "next expected", success, output_stream) return if n_expected_bytes_seen == 0 and len(expected_line) == 0: print("program produced", danger("output when no output was expected."), file=output_stream) print_line(actual_line, "unexpected", danger, output_stream) return if len(expected_line) == 0: print("of", danger("unexpected extra output."), file=output_stream) print( "The program produced all the expected output and then produced extra output.", file=output_stream) print_line(actual_line, "extra", danger, output_stream) return if is_last_expected_line and expected_byte == b'\n' and actual_char is None: print('the last', danger("newline was missing."), file=output_stream) print( "Your program produced all the expected output, except the last newline ('\\n') was missing.", file=output_stream) print("\nFor more information go to", explanation_url("missing_newline"), file=output_stream) return show_line_length = max(len(expected_line) + 8, 80) bad_characters_explanation = check_bad_characters(actual_line, line_number, danger, expected_line) if bad_characters_explanation: print(bad_characters_explanation, end='', file=output_stream) return print("of an", danger('incorrect output line.'), file=output_stream) print('Byte', actual_column + 1, 'of line', line_number, "of program output was incorrect.", file=output_stream) if not actual_line[actual_column + 1:]: if actual_line.rstrip(b'\n') + expected_byte == expected_line.rstrip( b'\n'): print("A", "'" + danger(sanitize(expected_byte)) + "'", "was missing from the end of the output line.", file=output_stream) elif actual_column > 1: print( "The characters you printed were correct, but more characters were expected.", file=output_stream) print("The correct output line was:", file=output_stream) print(success( sanitize(expected_line, max_line_length_shown=show_line_length)), file=output_stream) print("Your program printed this line:", file=output_stream) correct_prefix = success(sanitize(actual_line[0:actual_column])) print(correct_prefix, end='', file=output_stream) incorrect_byte = actual_line[actual_column:actual_column + 1] if incorrect_byte == ' ': print(danger(sanitize(incorrect_byte), bg='red'), end='', file=output_stream) else: print(danger(sanitize(incorrect_byte)), end='', file=output_stream) print(sanitize(actual_line[actual_column + 1:], max_line_length_shown=show_line_length - actual_column), file=output_stream)