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);
      }
    }
  }
}