These are some code I disassemble from msvcrt.dll(Windows XP2).
_flsbuf()
77C0ED01 cmp ebx, FFFFFFFF
77C0ED04 je 77C0ED1F
77C0ED06 mov ecx, ebx
77C0ED08 sar ecx, 05
77C0ED0B mov ecx, dword ptr [4*ecx+77C32440]
77C0ED12 mov eax, ebx
77C0ED14 and eax, 0000001F
77C0ED17 lea eax, dword ptr[eax+8*eax]
77C0ED1A lea eax, dword ptr[ecx+4*eax]
77C0ED1D jmp 77C0ED24
77C0ED1F mov eax, 77C2F310
77C0ED24 test [eax+04], 20
77C0ED28 je 77C0ED37
77C0ED2A push 00000002
77C0ED2C push 00000000
77C0ED2E push ebx
77C0ED2F call 77BFEFB0 /* call _lseek( ebx, 0, SEEK_END ) */
...
Please look at the red line instruction, after
"and eax, 0000001F"
the eax is less than 01Fh, right?
And ,
"dword ptr[eax+8*eax]",
the pointer is the value of "eax+8*eax",
and the result is much less than 4MB,
so I think the program reached the invalid memory.
I found this problem while I was debugging msvcrt.dll with my os. An pagefault occured to tell me that.
This is the source code of _flsbuf.c
Code: Select all
/***
*_flsbuf.c - flush buffer and output character.
*
* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _flsbuf() - flush a file buffer and output a character.
* If no buffer, make one.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <io.h>
#include <dbgint.h>
#include <malloc.h>
#include <msdos.h>
#include <wchar.h>
#include <internal.h>
#ifdef _MT
#include <mtdll.h>
#endif /* _MT */
#include <tchar.h>
/***
*int _flsbuf(ch, stream) - flush buffer and output character.
*
*Purpose:
* flush a buffer if this stream has one. if not, try to get one. put the
* next output char (ch) into the buffer (or output it immediately if this
* stream can't have a buffer). called only from putc. intended for use
* only within library.
*
* [NOTE: Multi-thread - It is assumed that the caller has aquired
* the stream lock.]
*
*Entry:
* FILE *stream - stream to flish and write on
* int ch - character to output.
*
*Exit:
* returns -1 if FILE is actually a string, or if can't write ch to
* unbuffered file, or if we flush a buffer but the number of chars
* written doesn't agree with buffer size. Otherwise returns ch.
* all fields in FILE struct can be affected except _file.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _flsbuf (
int ch,
FILE *str
)
{
REG1 FILE *stream;
REG2 int charcount;
REG3 int written;
int fh;
_ASSERTE(str != NULL);
/* Init file handle and pointers */
stream = str;
fh = _fileno(stream);
if (!(stream->_flag & (_IOWRT|_IORW)) || (stream->_flag & _IOSTRG)) {
stream->_flag |= _IOERR;
return(_TEOF);
}
if (stream->_flag & _IOREAD) {
stream->_cnt = 0;
if (stream->_flag & _IOEOF) {
stream->_ptr = stream->_base;
stream->_flag &= ~_IOREAD;
}
else {
stream->_flag |= _IOERR;
return(_TEOF);
}
}
stream->_flag |= _IOWRT;
stream->_flag &= ~_IOEOF;
written = charcount = stream->_cnt = 0;
/* Get a buffer for this stream, if necessary. */
if (!anybuf(stream)) {
if (!( ((stream==stdout) || (stream==stderr))
&& (_isatty(fh)) ))
_getbuf(stream);
} /* end !anybuf() */
/* If big buffer is assigned to stream... */
if (bigbuf(stream)) {
_ASSERTE(("inconsistent IOB fields", stream->_ptr - stream->_base >= 0));
charcount = stream->_ptr - stream->_base;
stream->_ptr = stream->_base + sizeof(TCHAR);
stream->_cnt = stream->_bufsiz - sizeof(TCHAR);
if (charcount > 0)
written = _write(fh, stream->_base, charcount);
else
if (_osfile_safe(fh) & FAPPEND) **** failed here****
_lseek(fh,0L,SEEK_END);
*stream->_base = (char)ch;
}
/* Perform single character output (either _IONBF or no buffering) */
else {
charcount = sizeof(TCHAR);
written = _write(fh, &ch, charcount);
}
/* See if the _write() was successful. */
if (written != charcount) {
stream->_flag |= _IOERR;
return(_TEOF);
}
return(ch & 0xff);
}