✅ [a108] InputHook MatchList: Invalid pointer read

Report problems with documented functionality
User avatar
lvalkov
Posts: 58
Joined: 08 Mar 2019, 16:39

✅ [a108] InputHook MatchList: Invalid pointer read

18 Apr 2020, 18:31

This issue has been resolved as of:

Code: Select all

Loop 1025
	matchList .= A_Index ','
matchList := RTrim(matchList, ',')

ih := InputHook('', '', matchList)

MsgBox ; Has already crashed by this point.

Code: Select all

ResultType input_type::SetMatchList(LPTSTR aMatchList, size_t aMatchList_length)
{
	LPTSTR *realloc_temp;  // Needed since realloc returns NULL on failure but leaves original block allocated.
	MatchCount = 0;  // Set default.
	if (*aMatchList)
	{
		// If needed, create the array of pointers that points into MatchBuf to each match phrase:
		if (!match)
		{
			if (   !(match = (LPTSTR *)malloc(INPUT_ARRAY_BLOCK_SIZE * sizeof(LPTSTR)))   )
				return g_script.ScriptError(ERR_OUTOFMEM);  // Short msg. since so rare.
			MatchCountMax = INPUT_ARRAY_BLOCK_SIZE;
		}
		// If needed, create or enlarge the buffer that contains all the match phrases:
		size_t space_needed = aMatchList_length + 1;  // +1 for the final zero terminator.
		if (space_needed > MatchBufSize)
		{
			MatchBufSize = (UINT)(space_needed > 4096 ? space_needed : 4096);
			if (MatchBuf) // free the old one since it's too small.
				free(MatchBuf);
			if (   !(MatchBuf = tmalloc(MatchBufSize))   )
			{
				MatchBufSize = 0;
				return g_script.ScriptError(ERR_OUTOFMEM);  // Short msg. since so rare.
			}
		}
		// Copy aMatchList into the match buffer:
		LPTSTR source, dest;
		for (source = aMatchList, dest = match[MatchCount] = MatchBuf
			; *source; ++source)
		{
			if (*source != ',') // Not a comma, so just copy it over.
			{
				*dest++ = *source;
				continue;
			}
			// Otherwise: it's a comma, which becomes the terminator of the previous key phrase unless
			// it's a double comma, in which case it's considered to be part of the previous phrase
			// rather than the next.
			if (*(source + 1) == ',') // double comma
			{
				*dest++ = *source;
				++source;  // Omit the second comma of the pair, i.e. each pair becomes a single literal comma.
				continue;
			}
			// Otherwise, this is a delimiting comma.
			*dest = '\0';
			// If the previous item is blank -- which I think can only happen now if the MatchList
			// begins with an orphaned comma (since two adjacent commas resolve to one literal comma)
			// -- don't add it to the match list:
			if (*match[MatchCount])
			{
				++MatchCount;
				match[MatchCount] = ++dest;
				*dest = '\0';  // Init to prevent crash on orphaned comma such as "btw,otoh,"
			}
			if (*(source + 1)) // There is a next element.
			{
				if (MatchCount >= MatchCountMax) // Rarely needed, so just realloc() to expand.
				{
					// Expand the array by one block:
					if (   !(realloc_temp = (LPTSTR *)realloc(match  // Must use a temp variable.
						, (MatchCountMax + INPUT_ARRAY_BLOCK_SIZE) * sizeof(LPTSTR)))   )
						return g_script.ScriptError(ERR_OUTOFMEM);  // Short msg. since so rare.
					match = realloc_temp;
					MatchCountMax += INPUT_ARRAY_BLOCK_SIZE;
				}
			}
		} // for()
		*dest = '\0';  // Terminate the last item.
		// This check is necessary for only a single isolated case: When the match list
		// consists of nothing except a single comma.  See above comment for details:
		if (*match[MatchCount]) // i.e. omit empty strings from the match list.
			++MatchCount;
	}
	return OK;
}
The crashes occur at:

Code: Select all

...
// If the previous item is blank -- which I think can only happen now if the MatchList
// begins with an orphaned comma (since two adjacent commas resolve to one literal comma)
// -- don't add it to the match list:
if (*match[MatchCount])
{
	++MatchCount;
	match[MatchCount] = ++dest;
	*dest = '\0';  // Init to prevent crash on orphaned comma such as "btw,otoh,"
}
...
or:

Code: Select all

...
// This check is necessary for only a single isolated case: When the match list
// consists of nothing except a single comma.  See above comment for details:
if (*match[MatchCount]) // i.e. omit empty strings from the match list.
	++MatchCount;
...
when MatchCount = 1024 and depending on the number of elements in the match list. At any rate, the number of elements has to exceed INPUT_ARRAY_BLOCK_SIZE (1024).

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 24 guests