static position_t isInBuffer(Buffer_t *This, mt_off_t start, size_t *len) { if(start >= This->current && start < This->current + This->cur_size) { maximize(*len, This->cur_size - OFFSET); return INSIDE; } else if(start == This->current + This->cur_size && This->cur_size < This->size && *len >= This->sectorSize) { /* append to the buffer for this, three conditions have to * be met: * 1. The start falls exactly at the end of the currently * loaded data * 2. There is still space * 3. We append at least one sector */ maximize(*len, This->size - This->cur_size); *len = ROUND_DOWN(*len, This->sectorSize); return APPEND; } else { if(invalidate_buffer(This, start) < 0) return ERROR; maximize(*len, This->cylinderSize - OFFSET); maximize(*len, This->cylinderSize - This->current % This->cylinderSize); return OUTSIDE; } }
size_t BufferedFile::read_unbuf( void* outbuf, const size_t size) { assert(m_file); assert(m_file_mode == ReadMode); assert(m_buffer); assert(outbuf); size_t bytes = 0; while (bytes < size) { // As soon as the I/O buffer is exhausted, switch to unbuffered reading. if (m_buffer_index == m_buffer_end) { m_file_index += static_cast<int64>(m_buffer_index); invalidate_buffer(); // Read all remaining data from disk directly into the output buffer. const size_t read = fread( &reinterpret_cast<uint8*>(outbuf)[bytes], 1, size - bytes, m_file); bytes += read; m_file_index += static_cast<int64>(read); break; } // Copy the contents of the I/O buffer into the output buffer. const size_t left = size - bytes; const size_t available = m_buffer_end - m_buffer_index; const size_t count = min(left, available); memcpy( &reinterpret_cast<uint8*>(outbuf)[bytes], &m_buffer[m_buffer_index], count); m_buffer_index += count; bytes += count; } return bytes; }
bool BufferedFile::seek( const int64 offset, const SeekOrigin origin) { assert(m_file); assert(m_buffer); // Seeking from the end is handled separately, since we don't know the size of the file. if (origin == SeekFromEnd) { if (m_file_mode == ReadMode) invalidate_buffer(); else flush_buffer(); if (portable_fseek(m_file, offset, SEEK_END)) return false; m_file_index = portable_ftell(m_file); } else { int64 target_index; if (origin == SeekFromBeginning) target_index = offset; else { assert(origin == SeekFromCurrent); const int64 current_index = m_file_index + static_cast<int64>(m_buffer_index); target_index = max<int64>(current_index + offset, 0); } if (target_index >= m_file_index && target_index < m_file_index + static_cast<int64>(m_buffer_end)) { // Seek within the I/O buffer. m_buffer_index = static_cast<size_t>(target_index - m_file_index); } else { int64 current_file_index; if (m_file_mode == ReadMode) { current_file_index = m_file_index + static_cast<int64>(m_buffer_end); invalidate_buffer(); } else { current_file_index = m_file_index; flush_buffer(); } if (portable_fseek(m_file, target_index - current_file_index, SEEK_CUR)) return false; m_file_index = portable_ftell(m_file); } } return true; }
void string_instrumentationt::do_format_string_write( goto_programt &dest, goto_programt::const_targett target, const code_function_callt::argumentst &arguments, unsigned format_string_inx, unsigned argument_start_inx, const std::string &function_name) { const exprt &format_arg = arguments[format_string_inx]; if(format_arg.id()=="address_of" && format_arg.op0().id()=="index" && format_arg.op0().op0().id()==ID_string_constant) // constant format { format_token_listt token_list; parse_format_string(format_arg.op0().op0(), token_list); unsigned args=0; for(format_token_listt::const_iterator it=token_list.begin(); it!=token_list.end(); it++) { if(find(it->flags.begin(), it->flags.end(), format_tokent::ASTERISK)!= it->flags.end()) continue; // asterisk means `ignore this' switch(it->type) { case format_tokent::STRING: { const exprt &argument=arguments[argument_start_inx+args]; const typet &arg_type=ns.follow(argument.type()); goto_programt::targett assertion=dest.add_instruction(); assertion->location=target->location; assertion->location.set("property", "string"); std::string comment("format string buffer overflow in "); comment += function_name; assertion->location.set("comment", comment); if(it->field_width!=0) { exprt fwidth = from_integer(it->field_width, uint_type()); exprt fw_1("+", uint_type()); exprt one = gen_one(uint_type()); fw_1.move_to_operands(fwidth); fw_1.move_to_operands(one); // +1 for 0-char exprt fw_lt_bs; if(arg_type.id()=="pointer") fw_lt_bs=binary_relation_exprt(fw_1, "<=", buffer_size(argument)); else { index_exprt index; index.array()=argument; index.index()=gen_zero(uint_type()); address_of_exprt aof(index); fw_lt_bs=binary_relation_exprt(fw_1, "<=", buffer_size(aof)); } assertion->make_assertion(fw_lt_bs); } else { // this is a possible overflow. assertion->make_assertion(false_exprt()); } // now kill the contents invalidate_buffer(dest, target, argument, arg_type, it->field_width); args++; break; } case format_tokent::TEXT: case format_tokent::UNKNOWN: { // nothing break; } default: // everything else { const exprt &argument=arguments[argument_start_inx+args]; const typet &arg_type=ns.follow(argument.type()); goto_programt::targett assignment=dest.add_instruction(ASSIGN); assignment->location=target->location; exprt lhs("dereference", arg_type.subtype()); lhs.copy_to_operands(argument); exprt rhs=side_effect_expr_nondett(lhs.type()); rhs.location()=target->location; assignment->code=code_assignt(lhs, rhs); args++; break; } } } } else // non-const format string { for(unsigned i=argument_start_inx; i<arguments.size(); i++) { const typet &arg_type=ns.follow(arguments[i].type()); // Note: is_string_type() is a `good guess' here. Actually // any of the pointers could point into an array. But it // would suck if we had to invalidate all variables. // Luckily this case isn't needed too often. if(is_string_type(arg_type)) { goto_programt::targett assertion=dest.add_instruction(); assertion->location=target->location; assertion->location.set("property", "string"); std::string comment("format string buffer overflow in "); comment += function_name; assertion->location.set("comment", comment); // as we don't know any field width for the %s that // should be here during runtime, we just report a // possibly false positive assertion->make_assertion(false_exprt()); invalidate_buffer(dest, target, arguments[i], arg_type, 0); } else { goto_programt::targett assignment = dest.add_instruction(ASSIGN); assignment->location=target->location; exprt lhs("dereference", arg_type.subtype()); lhs.copy_to_operands(arguments[i]); exprt rhs=side_effect_expr_nondett(lhs.type()); rhs.location()=target->location; assignment->code=code_assignt(lhs, rhs); } } } }