Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent memory overflow in compilePassOpcode #1185

Merged
merged 1 commit into from
May 30, 2022
Merged

Conversation

mgieseki
Copy link
Contributor

This is a proposal to fix issue #1171. To prevent writing past the CharsString memory block, I replaced all assignments to passInstructions[passIC++] with macro APPEND_INSTRUCTION_CHAR(ch) that checks the validity of index passIC before assigning a value.
The sample file used to trigger the buffer overflow in #1171 only affects pass_lookback. But since there are a couple of similar sections that append more than one character without checking the index, I adapted all of them. The "ugly" macro could be replaced by dedicated index checks to reduce the number of if statements and to speed up the code a bit, but I decided against that to avoid code bloat.

@mgieseki mgieseki changed the title prevent memory overflow in compilePastOpcode prevent memory overflow in compilePassOpcode Mar 22, 2022
@bertfrees bertfrees added the memory error Buffer overflow, use after free, memory leak, ... label Mar 22, 2022
@bertfrees bertfrees added this to the 3.22 milestone Mar 28, 2022
Copy link
Member

@bertfrees bertfrees left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! But why do we need a macro? Couldn't it be done with a function?

If we do need a macro I suggest we wrap it in do {...} while (0).

@mgieseki
Copy link
Contributor Author

mgieseki commented Mar 28, 2022

I think we need a macro if we want to leave function compilePassOpcode once the maximum string length is reached. Otherwise, another check containing a return statement must be added inside compilePassOpcode.

Maybe it's not necessary to check the index for each single character and we can avoid to introduce the macro. If I counted correctly, there's a maximum number of 7 potentially untested assignments to passInstructions[passIC++] per loop iteration. So it would be sufficient to ensure that there's enough space to hold 7 additional characters at the beginning of the loop body. I.e. replacing line

if (passIC >= MAXSTRING) {

with

if (passIC >= MAXSTRING-6) {

should also fix the issue, but I haven't tested it properly yet.

@bertfrees
Copy link
Member

Like this?

if (!append_instruction_char(passInstructions, &passIC, pass_lookback)) return 0;

I prefer that over a macro.

if (passIC >= MAXSTRING-6)

I could live with this solution too, if it's explained what the "6" is, and in such a way that it's obvious the number needs to be updated when we modify compilePassOpcode elsewhere. This probably means explaining the structure of the passInstructions array at the beginning of the function.

@mgieseki
Copy link
Contributor Author

Like this?

if (!append_instruction_char(passInstructions, &passIC, pass_lookback)) return 0;

Yes, exactly.

I prefer that over a macro.

Ok, sure. I can adapt the code accordingly. In case you prefer the repetitive checks over a single check at the beginning of the loop body, I'll change the PR that way. If you happen to have already adapted the code yourself, you can of course commit your changes as well.

@bertfrees
Copy link
Member

bertfrees commented Mar 28, 2022

This probably means explaining the structure of the passInstructions array at the beginning of the function.

I've done a first attempt with this table:

_ _ 1
_99 _ 99
! !
` `
~ ~
/ /
"foo" " 3 f o o
@12-34-45 @ 3 * * *
[ [
] ]
#1=99 = 1 99
#1<99 < 1 99
#1<=99 130 1 99
#1>99 > 1 99
#1<=99 131 1 99
#1+ + 1
#1- - 1
$d $ * * * * 1 1
$d. $ * * * * 1 0xffff
$d9 $ * * * * 9 9
$d9-99 $ * * * * 9 99
{foo { * *
}foo } * *
;foo ; * *
%foo (character class) % * * * * 1 1
%foo. % * * * * 1 0xffff
%foo9 % * * * * 9 9
%foo9-99 % * * * * 9 99
%foo (swap class) % * * 1 1
%foo. % * * 1 0xffff
%foo9 % * * 9 9
%foo9-99 % * * 9 99
* *
? ?
(end of test, begin of action) 32 (space)

(created a new issue for this: #1215)

@mgieseki
Copy link
Contributor Author

I've replaced the macro with a function.

@bertfrees
Copy link
Member

Thanks.

@mgieseki
Copy link
Contributor Author

Should I run clang-format -i on compileTranslationTable.c in order to fix the format check, or do you take care of this?

@bertfrees
Copy link
Member

Yes you may do it, otherwise we'll take care of it.

if (!appendInstructionChar(file, passInstructions, &passIC, 1)) return 0;
passHoldNumber = passInstructions[passIC - 1];
if (!appendInstructionChar(file, passInstructions, &passIC, 1))
return 0; /* This is not an error */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is really confusing now. It should stay with the line above as in the original.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed the comment, and also removed the passHoldNumber = passInstructions[passIC - 1]; line because it was not needed.

@bertfrees bertfrees force-pushed the master branch 2 times, most recently from 0862fc1 to 779a877 Compare May 25, 2022 22:20
@bertfrees bertfrees removed their assignment May 26, 2022
@egli egli merged commit 49f4ee3 into liblouis:master May 30, 2022
@egli egli removed the needs news Update to NEWS file needed label May 30, 2022
@egli egli linked an issue May 30, 2022 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
memory error Buffer overflow, use after free, memory leak, ...
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] global-buffer-overflow in lou_checktable
3 participants