libcamera: controls: guard ControlInfoMap against nullptr idmap_

It's possible to construct a Camera with an unsafe controlInfo_.
This is the case in the Simple pipeline, where the camera controls are
not populated.

With Simple, if we attempt to set a Control, we end up with a segfault
because the default constructor for ControlInfoMap doesn't
intialized idmap_ which is initialized at class declaration time as

  const ControlIdMap *idmap_ = nullptr;

Add some safeguards in ControlInfoMap to handle this case.

Link: https://lists.libcamera.org/pipermail/libcamera-devel/2023-April/037439.html
Suggested-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Mattijs Korpershoek 2023-04-05 10:14:30 +02:00 committed by Kieran Bingham
parent 46852241a3
commit 3dc2605bda

View file

@ -677,6 +677,9 @@ ControlInfoMap::ControlInfoMap(Map &&info, const ControlIdMap &idmap)
bool ControlInfoMap::validate() bool ControlInfoMap::validate()
{ {
if (!idmap_)
return false;
for (const auto &ctrl : *this) { for (const auto &ctrl : *this) {
const ControlId *id = ctrl.first; const ControlId *id = ctrl.first;
auto it = idmap_->find(id->id()); auto it = idmap_->find(id->id());
@ -719,6 +722,8 @@ bool ControlInfoMap::validate()
*/ */
ControlInfoMap::mapped_type &ControlInfoMap::at(unsigned int id) ControlInfoMap::mapped_type &ControlInfoMap::at(unsigned int id)
{ {
ASSERT(idmap_);
return at(idmap_->at(id)); return at(idmap_->at(id));
} }
@ -729,6 +734,8 @@ ControlInfoMap::mapped_type &ControlInfoMap::at(unsigned int id)
*/ */
const ControlInfoMap::mapped_type &ControlInfoMap::at(unsigned int id) const const ControlInfoMap::mapped_type &ControlInfoMap::at(unsigned int id) const
{ {
ASSERT(idmap_);
return at(idmap_->at(id)); return at(idmap_->at(id));
} }
@ -739,6 +746,9 @@ const ControlInfoMap::mapped_type &ControlInfoMap::at(unsigned int id) const
*/ */
ControlInfoMap::size_type ControlInfoMap::count(unsigned int id) const ControlInfoMap::size_type ControlInfoMap::count(unsigned int id) const
{ {
if (!idmap_)
return 0;
/* /*
* The ControlInfoMap and its idmap have a 1:1 mapping between their * The ControlInfoMap and its idmap have a 1:1 mapping between their
* entries, we can thus just count the matching entries in idmap to * entries, we can thus just count the matching entries in idmap to
@ -755,6 +765,9 @@ ControlInfoMap::size_type ControlInfoMap::count(unsigned int id) const
*/ */
ControlInfoMap::iterator ControlInfoMap::find(unsigned int id) ControlInfoMap::iterator ControlInfoMap::find(unsigned int id)
{ {
if (!idmap_)
return end();
auto iter = idmap_->find(id); auto iter = idmap_->find(id);
if (iter == idmap_->end()) if (iter == idmap_->end())
return end(); return end();
@ -770,6 +783,9 @@ ControlInfoMap::iterator ControlInfoMap::find(unsigned int id)
*/ */
ControlInfoMap::const_iterator ControlInfoMap::find(unsigned int id) const ControlInfoMap::const_iterator ControlInfoMap::find(unsigned int id) const
{ {
if (!idmap_)
return end();
auto iter = idmap_->find(id); auto iter = idmap_->find(id);
if (iter == idmap_->end()) if (iter == idmap_->end())
return end(); return end();