Skip to content

Commit 6c29405

Browse files
committed
uefi/gop: fix memory leak
1 parent 55c7026 commit 6c29405

File tree

3 files changed

+28
-12
lines changed

3 files changed

+28
-12
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## uefi - [Unreleased]
44

5+
### Changed
6+
- We fixed a memory leak in `GraphicsOutput::query_mode`. As a consequence, we
7+
had to add `&BootServices` as additional parameter.
8+
59
## uefi-macros - [Unreleased]
610

711
## uefi-raw - [Unreleased]

uefi-test-runner/src/proto/console/gop.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub unsafe fn test(image: Handle, bt: &BootServices) {
2222
)
2323
.expect("failed to open Graphics Output Protocol");
2424

25-
set_graphics_mode(gop);
25+
set_graphics_mode(gop, bt);
2626
fill_color(gop);
2727
draw_fb(gop);
2828

@@ -33,10 +33,10 @@ pub unsafe fn test(image: Handle, bt: &BootServices) {
3333
}
3434

3535
// Set a larger graphics mode.
36-
fn set_graphics_mode(gop: &mut GraphicsOutput) {
36+
fn set_graphics_mode(gop: &mut GraphicsOutput, bs: &BootServices) {
3737
// We know for sure QEMU has a 1024x768 mode.
3838
let mode = gop
39-
.modes()
39+
.modes(bs)
4040
.find(|mode| {
4141
let info = mode.info();
4242
info.resolution() == (1024, 768)

uefi/src/proto/console/gop.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
//! You will have to implement your own double buffering if you want to
5151
//! avoid tearing with animations.
5252
53+
use crate::prelude::BootServices;
5354
use crate::proto::unsafe_protocol;
5455
use crate::util::usize_from_u32;
5556
use crate::{Result, StatusExt};
@@ -75,27 +76,37 @@ pub struct GraphicsOutput(GraphicsOutputProtocol);
7576
impl GraphicsOutput {
7677
/// Returns information for an available graphics mode that the graphics
7778
/// device and the set of active video output devices supports.
78-
pub fn query_mode(&self, index: u32) -> Result<Mode> {
79+
pub fn query_mode(&self, index: u32, bs: &BootServices) -> Result<Mode> {
7980
let mut info_sz = 0;
80-
let mut info = ptr::null();
81+
let mut info_heap_ptr = ptr::null();
82+
// query_mode allocates a buffer and stores the heap ptr in the provided
83+
// variable. In this buffer, the queried data can be found.
84+
unsafe { (self.0.query_mode)(&self.0, index, &mut info_sz, &mut info_heap_ptr) }
85+
.to_result_with_val(|| {
86+
// Transform to owned info on the stack.
87+
let info = unsafe { *info_heap_ptr };
88+
89+
let info_heap_ptr = info_heap_ptr.cast::<u8>().cast_mut();
90+
91+
// User has no benefit from propagating this error. If this
92+
// fails, it is an error of the UEFI implementation.
93+
bs.free_pool(info_heap_ptr)
94+
.expect("buffer should be deallocatable");
8195

82-
unsafe { (self.0.query_mode)(&self.0, index, &mut info_sz, &mut info) }.to_result_with_val(
83-
|| {
84-
let info = unsafe { *info };
8596
Mode {
8697
index,
8798
info_sz,
8899
info: ModeInfo(info),
89100
}
90-
},
91-
)
101+
})
92102
}
93103

94104
/// Returns information about all available graphics modes.
95105
#[must_use]
96-
pub fn modes(&self) -> ModeIter {
106+
pub fn modes<'a>(&'a self, bs: &'a BootServices) -> ModeIter {
97107
ModeIter {
98108
gop: self,
109+
bs,
99110
current: 0,
100111
max: self.mode().max_mode,
101112
}
@@ -400,6 +411,7 @@ impl ModeInfo {
400411
/// Iterator for [`Mode`]s of the [`GraphicsOutput`] protocol.
401412
pub struct ModeIter<'gop> {
402413
gop: &'gop GraphicsOutput,
414+
bs: &'gop BootServices,
403415
current: u32,
404416
max: u32,
405417
}
@@ -410,7 +422,7 @@ impl<'gop> Iterator for ModeIter<'gop> {
410422
fn next(&mut self) -> Option<Self::Item> {
411423
let index = self.current;
412424
if index < self.max {
413-
let m = self.gop.query_mode(index);
425+
let m = self.gop.query_mode(index, self.bs);
414426
self.current += 1;
415427

416428
m.ok().or_else(|| self.next())

0 commit comments

Comments
 (0)