Skip to content

Commit 423d128

Browse files
committed
uefi/gop: fix memory leak
1 parent 55c7026 commit 423d128

File tree

3 files changed

+29
-14
lines changed

3 files changed

+29
-14
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

+22-11
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,19 @@
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};
5657
use core::fmt::{Debug, Formatter};
5758
use core::marker::PhantomData;
5859
use core::{mem, ptr};
60+
pub use uefi_raw::protocol::console::PixelBitmask;
5961
use uefi_raw::protocol::console::{
6062
GraphicsOutputBltOperation, GraphicsOutputModeInformation, GraphicsOutputProtocol,
6163
GraphicsOutputProtocolMode,
6264
};
6365

64-
pub use uefi_raw::protocol::console::PixelBitmask;
65-
6666
/// Provides access to the video hardware's frame buffer.
6767
///
6868
/// The GOP can be used to set the properties of the frame buffer,
@@ -75,27 +75,37 @@ pub struct GraphicsOutput(GraphicsOutputProtocol);
7575
impl GraphicsOutput {
7676
/// Returns information for an available graphics mode that the graphics
7777
/// device and the set of active video output devices supports.
78-
pub fn query_mode(&self, index: u32) -> Result<Mode> {
78+
pub fn query_mode(&self, index: u32, bs: &BootServices) -> Result<Mode> {
7979
let mut info_sz = 0;
80-
let mut info = ptr::null();
80+
let mut info_heap_ptr = ptr::null();
81+
// query_mode allocates a buffer and stores the heap ptr in the provided
82+
// variable. In this buffer, the queried data can be found.
83+
unsafe { (self.0.query_mode)(&self.0, index, &mut info_sz, &mut info_heap_ptr) }
84+
.to_result_with_val(|| {
85+
// Transform to owned info on the stack.
86+
let info = unsafe { *info_heap_ptr };
87+
88+
let info_heap_ptr = info_heap_ptr.cast::<u8>().cast_mut();
89+
90+
// User has no benefit from propagating this error. If this
91+
// fails, it is an error of the UEFI implementation.
92+
bs.free_pool(info_heap_ptr)
93+
.expect("buffer should be deallocatable");
8194

82-
unsafe { (self.0.query_mode)(&self.0, index, &mut info_sz, &mut info) }.to_result_with_val(
83-
|| {
84-
let info = unsafe { *info };
8595
Mode {
8696
index,
8797
info_sz,
8898
info: ModeInfo(info),
8999
}
90-
},
91-
)
100+
})
92101
}
93102

94103
/// Returns information about all available graphics modes.
95104
#[must_use]
96-
pub fn modes(&self) -> ModeIter {
105+
pub fn modes<'a>(&'a self, bs: &'a BootServices) -> ModeIter {
97106
ModeIter {
98107
gop: self,
108+
bs,
99109
current: 0,
100110
max: self.mode().max_mode,
101111
}
@@ -400,6 +410,7 @@ impl ModeInfo {
400410
/// Iterator for [`Mode`]s of the [`GraphicsOutput`] protocol.
401411
pub struct ModeIter<'gop> {
402412
gop: &'gop GraphicsOutput,
413+
bs: &'gop BootServices,
403414
current: u32,
404415
max: u32,
405416
}
@@ -410,7 +421,7 @@ impl<'gop> Iterator for ModeIter<'gop> {
410421
fn next(&mut self) -> Option<Self::Item> {
411422
let index = self.current;
412423
if index < self.max {
413-
let m = self.gop.query_mode(index);
424+
let m = self.gop.query_mode(index, self.bs);
414425
self.current += 1;
415426

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

0 commit comments

Comments
 (0)