crash in SphericalCap::drawFill()

Bug #1173355 reported by Emmanuel on 2013-04-26
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Stellarium
Fix Released
Medium
Emmanuel

Bug Description

The following code
    {
        renderer->setGlobalColor(0,1,0,0);
        SphericalCap C(1,0,0);
        StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
        SphericalRegion::DrawParams dp(prj.data());
        C.drawFill(renderer, dp);
    }
inserted at the very beginning of the draw() method of the AngleMeasure plugin, compiled statically, causes stellarium to crash

Stellarium versions tested: 0.12.0 and 0.12 on linux, and 0.12.0 on windows.

Console output:
Loaded plugin "AngleMeasure" .
AngleMeasure plugin - press control-A to toggle angle measure mode
Build log after adding a Mat4d transform shader: "Built successfully"
Build log after adding a stereographic projection shader: "Built successfully"
Simple planet shader build log: "Built successfully"
Shadow planet shader build log: "Built successfully"
Using vertex shader for atmosphere rendering.
Atmosphere shader build log: "Built successfully"
ASSERT failure in void appendTriangle(StelVertexBuffer<SphericalRegion::PlainVertex>*, const Triplet<Vector3<float> >&, const Triplet<Vector2<float> >*): "Got texCoords even though building buffer without texture coords", file /home/emmanuel/stellarium/0.12/0.12/src/core/StelSphereGeometry.cpp, line 326
Abandon

Backtrace from gdb:
Program received signal SIGABRT, Aborted.
0x00007ffff5ad9425 in __GI_raise (sig=<optimized out>)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: Aucun fichier ou dossier de ce type.
(gdb) bt
#0 0x00007ffff5ad9425 in __GI_raise (sig=<optimized out>)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007ffff5adcb8b in __GI_abort () at abort.c:91
#2 0x00007ffff61f04c2 in qt_message_output(QtMsgType, char const*) ()
   from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#3 0x00007ffff61f0838 in ?? () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#4 0x00007ffff61f09c4 in qFatal(char const*, ...) ()
   from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#5 0x000000000055c3ec in appendTriangle (buffer=0x2add2c0, vertices=...,
    texCoords=0x7fffffffa120)
    at /home/emmanuel/stellarium/0.12/0.12/src/core/StelSphereGeometry.cpp:325
#6 0x000000000056b86f in projectSphericalTriangle<SphericalRegion::PlainVertex> (projector=0x2adc4b0, clippingCap=0x0, vertices=0x7fffffffa1a0,
    texCoords=0x7fffffffa120, buffer=0x2add2c0, maxSqDistortion=5, nbI=1,
    checkDisc1=true, checkDisc2=true, checkDisc3=false)
    at /home/emmanuel/stellarium/0.12/0.12/src/core/StelSphereGeometry.cpp:430
#7 0x000000000056bc4a in projectSphericalTriangle<SphericalRegion::PlainVertex> (projector=0x2adc4b0, clippingCap=0x0, vertices=0x7fffffffa2a0,
    texCoords=0x0, buffer=0x2add2c0, maxSqDistortion=5, nbI=0,
    checkDisc1=true, checkDisc2=true, checkDisc3=true)
    at /home/emmanuel/stellarium/0.12/0.12/src/core/StelSphereGeometry.cpp:466
#8 0x000000000055c995 in SphericalRegion::updateFillVertexBuffer (
    this=0x7fffffffa620, renderer=0xd52990, params=...,
---Type <return> to continue, or q <return> to quit---
    handleDiscontinuity=false)
    at /home/emmanuel/stellarium/0.12/0.12/src/core/StelSphereGeometry.cpp:814
#9 0x000000000055d6dd in SphericalRegion::drawFill (this=0x7fffffffa620,
    renderer=0xd52990, params=...)
    at /home/emmanuel/stellarium/0.12/0.12/src/core/StelSphereGeometry.cpp:994
#10 0x000000000071d80e in AngleMeasure::draw (this=0x263fa90, core=0xf8e4e0,
    renderer=0xd52990)
    at /home/emmanuel/stellarium/0.12/0.12/plugins/AngleMeasure/src/AngleMeasure.cpp:158

Code of modified AngleMesure.cpp:
150 //! Draw any parts on the screen which are for our module
151 void AngleMeasure::draw(StelCore* core, StelRenderer* renderer)
152 {
153 {
154 renderer->setGlobalColor(0,1,0,0);
155 SphericalCap C(1,0,0);
156 StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
157 SphericalRegion::DrawParams dp(prj.data());
158 C.drawFill(renderer, dp);
159 }
160 if (lineVisible.getInterstate() < 0.000001f && messageFader.getInter state() < 0.000001f)
161 return;
162

Related branches

Emmanuel (hacker-emmanuel) wrote :

In fact the crash is a failed assertion which appears in debug mode.

By commenting out this assertion, there are then three other failed assertions at StelSphereGeometry.cpp:373
      Q_ASSERT(fabs(vertices->a.length()-1.)<0.00001);
      Q_ASSERT(fabs(vertices->b.length()-1.)<0.00001);
      Q_ASSERT(fabs(vertices->c.length()-1.)<0.00001);

By commenting them out, the code does not crash but the spherical cap is not correctly drawn and the program eventually crashes (except in gdb and valgrind)
(nb: there's a mistake in the code sample I gave, the alpha channel should be 1 to see something, and it's better to set a small aperture to the spherical cap)

Under valgrind the spherical cap is correctly drawn and the program does not crash, but there are many "Invalid read" errors from freed memory blocks.

Few weeks ago everything worked with basically the same code. Since then I upgraded graphics card drivers. That's the only thing I can think of but I don't understand how it could explain these new issues.

Emmanuel (hacker-emmanuel) wrote :

There is what looks like an actual memory handling error in the code that explains the three last failed assertions as well as the spherical cap not rendering properly.

This is in these excerpts of StelSphereGeometry.cpp and OctahedronPolygon.hpp:

 760 void SphericalRegion::updateFillVertexBuffer(StelRenderer* renderer, const DrawParams& params, bool handleDiscontinuity)
 761 {
 762 const QVector<Vec3d> &vertices = getOctahedronPolygon().fillVertices ();

1337 OctahedronPolygon SphericalCap::getOctahedronPolygon() const
1338 {
1339 if (d>=0)
1340 return OctahedronPolygon(getClosedOutlineContour());

113 //! Get vertices forming triangles filling out the polygon.
114 const QVector<Vec3d>& fillVertices() const
115 {
116 return fillCachedVertexArray;

160 //! Vertex array storing triangles of the polygon (each 3 vertices b eing one triangle).
161 QVector<Vec3d> fillCachedVertexArray;

=> vertices is defined as a reference to a field of a temporary OctahedronPolygon object that gets destroyed right after the definition of 'vertices'
=> in the rest of the SphericalRegion::updateFillVertexBuffer() method it is not legit to use 'vertices', but that's what is done, and why it sometimes crashes

Replacing:
 762 const QVector<Vec3d> &vertices = getOctahedronPolygon().fillVertices ();
With:
 762 const QVector<Vec3d> vertices = getOctahedronPolygon().fillVertices ();
solves the issue (but that's just to demonstrate the problem, not an optimal solution)

The initial issue of the first assertion that fails in debug mode remains though.

Emmanuel (hacker-emmanuel) wrote :

The initial failed assertion issue of this bug report can be traced to file StelSphericalGeometry.cpp:

 319 //! @param texCoords Texture coordinates of vertices in the triangle.
 320 //! Must be NULL for this overload.
 321 void appendTriangle(StelVertexBuffer<SphericalRegion::PlainVertex>* buffer,
 322 const Triplet<Vec3f>& vertices, const Triplet<Vec2f>* t exCoords)
 323 {
 324 #ifndef NDEBUG
 325 Q_ASSERT_X(texCoords == NULL, Q_FUNC_INFO,
 326 "Got texCoords even though building buffer without textu re coords");

The appendTriangle method is improperly called from:

 360 template<class V>
 361 void projectSphericalTriangle
 ...
 430 appendTriangle(buffer, triangle, texCoords);

Which is itself called from:

 619 if (NULL != texCoords)
 620 {
 621 ta.a=(texCoords->a+texCoords->b)*0.5;
 622 ta.b=texCoords->b;
 623 ta.c=texCoords->c;
 624 }
 625 projectSphericalTriangle(projector, clippingCap, &va, texCoords ? &ta : 0, buffer, maxSqDistortion, nbI+1, true, false, true);

If texCoord is null, denoting that the vertex buffer was produced with no texture, a non-null texcoord pointer is nevertheless passed to appendTriangle() which according to comment on line 320 is not correct.

To fix this, calls like:
 625 projectSphericalTriangle(projector, clippingCap, &va, &ta, buffer, maxSqDistortion, nbI+1, true, false, true);
Could be replaced with:
 625 projectSphericalTriangle(projector, clippingCap, &va, texCoords ? &ta : 0, buffer, maxSqDistortion, nbI+1, true,

Otherwise, why not remove the assertion if there is no ill effect?

Emmanuel (hacker-emmanuel) wrote :

I realize that previous comments need a few edits for typos and mistakes but overall the meaning should be recoverable.

Anyway in comment #4 the current problematic stellarium implementation of StelSphereGeometry is:
625 projectSphericalTriangle(projector, clippingCap, &va, &ta, buffer, maxSqDistortion, nbI+1, true, false, true);
and not:
625 projectSphericalTriangle(projector, clippingCap, &va, texCoords ? &ta : 0, buffer, maxSqDistortion, nbI+1, true,
as suggested in the code extract. The latter is actually the proposed correction.

In comment #2 a more efficient solution for fixing the memory handling error would be replacing:
  762 const QVector<Vec3d> &vertices = getOctahedronPolygon().fillVertices ();
With:
 762 const OctahedronPolygon &octahedron = getOctahedronPolygon();
 763 const QVector<Vec3d> &vertices = octahedron.fillVertices ();
The added const reference on temporary object 'octahedron' extends its lifetime so that it is now legit to get a reference to its vertices and use it in the scope of the function. Doing so the program no longer crashes and valgrind no longer complains.

These issues seemingly arise only for third-party plugin developpers using otherwise unused stellarium code, so does not affect users of the stellarium base application and plugins, and is not immediate to reproduce.
For my immediate concern it's possible to embed a corrected redefinition of the relevant functions in my plugins to supersede the original ones, but ultimately it would be better to fix the stellarium code base.
Would that be ok for me to submit a patch including the above-mentionned corrections?

Alexander Wolf (alexwolf) wrote :

Yes, you should prepare a patch and attach it (or propose via branch).

Changed in stellarium:
milestone: none → 0.12.2
assignee: nobody → Emmanuel (hacker-emmanuel)
status: New → Fix Committed
Changed in stellarium:
importance: Undecided → Medium
Changed in stellarium:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Related questions