[libbluray-devel] Improve detection and handling of broken and encrypted blocks

hpi1 git at videolan.org
Wed Apr 15 11:22:26 CEST 2015


libbluray | branch: master | hpi1 <hpi1 at anonymous.org> | Fri Apr 10 15:02:59 2015 +0300| [18fd1f697ef1372439bcd8fdb44d4d9a5d040046] | committer: hpi1

Improve detection and handling of broken and encrypted blocks

> http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=18fd1f697ef1372439bcd8fdb44d4d9a5d040046
---

 ChangeLog              |    2 ++
 src/libbluray/bluray.c |   57 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 316e68a..365c23d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+- Improved error resilence.
+
 2015-04-15: Version 0.8.0
 - Add security checks to BD-J.
 - Add support for UDF image files and unmounted discs.
diff --git a/src/libbluray/bluray.c b/src/libbluray/bluray.c
index 95b6d65..5fb20a6 100644
--- a/src/libbluray/bluray.c
+++ b/src/libbluray/bluray.c
@@ -91,6 +91,7 @@ typedef struct {
 
     /* */
     uint8_t         eof_hit;
+    uint8_t         encrypted_block_cnt;
 
     M2TS_FILTER    *m2ts_filter;
 } BD_STREAM;
@@ -544,6 +545,7 @@ static int _open_m2ts(BLURAY *bd, BD_STREAM *st)
     st->clip_pos = (uint64_t)st->clip->start_pkt * 192;
     st->clip_block_pos = (st->clip_pos / 6144) * 6144;
     st->eof_hit = 0;
+    st->encrypted_block_cnt = 0;
 
     if (st->fp) {
         int64_t clip_size = file_size(st->fp);
@@ -589,6 +591,42 @@ static int _open_m2ts(BLURAY *bd, BD_STREAM *st)
     return 0;
 }
 
+static int _validate_unit(BLURAY *bd, BD_STREAM *st, uint8_t *buf)
+{
+    /* Check TP_extra_header Copy_permission_indicator. If != 0, unit may be encrypted. */
+    /* Check first sync byte. It should never be encrypted. */
+    if (BD_UNLIKELY(buf[0] & 0xc0 || buf[4] != 0x47)) {
+
+        /* Check first sync bytes. If not OK, drop unit. */
+        if (buf[4] != 0x47 || buf [4 + 192] != 0x47 || buf[4 + 2*192] != 0x47 || buf[4 + 3*192] != 0x47) {
+
+            /* Some streams have Copy_permission_indicator incorrectly set. */
+            /* Check first TS sync byte. If unit is encrypted, first 16 bytes are plain, rest not. */
+            /* not 100% accurate (can be random data too). But the unit is broken anyway ... */
+            if (buf[4] == 0x47) {
+
+                /* most likely encrypted stream. Check couple of blocks before erroring out. */
+                st->encrypted_block_cnt++;
+
+                if (st->encrypted_block_cnt > 10) {
+                    /* error out */
+                    BD_DEBUG(DBG_BLURAY | DBG_CRIT, "TP header copy permission indicator != 0. Stream seems to be encrypted.\n");
+                    _queue_event(bd, BD_EVENT_ENCRYPTED, BD_ERROR_AACS);
+                    return -1;
+                }
+            }
+
+            /* broken block, ignore it */
+            _queue_event(bd, BD_EVENT_READ_ERROR, 1);
+            return 0;
+        }
+    }
+
+    st->eof_hit = 0;
+    st->encrypted_block_cnt = 0;
+    return 1;
+}
+
 static int _read_block(BLURAY *bd, BD_STREAM *st, uint8_t *buf)
 {
     const size_t len = 6144;
@@ -600,21 +638,18 @@ static int _read_block(BLURAY *bd, BD_STREAM *st, uint8_t *buf)
             size_t read_len;
 
             if ((read_len = file_read(st->fp, buf, len))) {
+                int error;
+
                 if (read_len != len) {
                     BD_DEBUG(DBG_STREAM | DBG_CRIT, "Read %d bytes at %"PRIu64" ; requested %d !\n", (int)read_len, st->clip_block_pos, (int)len);
                 }
                 st->clip_block_pos += len;
-                st->eof_hit = 0;
-
-                /* Check TP_extra_header Copy_permission_indicator. If != 0, unit is still encrypted. */
-                if (buf[0] & 0xc0) {
-                    /* check first TS sync bytes. First 16 bytes are always plain. */
-                    if (buf[4] == 0x47 && (buf[4+192] != 0x47 || buf[4+2*192] != 0x47)) {
-                        BD_DEBUG(DBG_BLURAY | DBG_CRIT,
-                                 "TP header copy permission indicator != 0, unit is still encrypted?\n");
-                        _queue_event(bd, BD_EVENT_ENCRYPTED, BD_ERROR_AACS);
-                        return -1;
-                    }
+
+                if ((error = _validate_unit(bd, st, buf)) <= 0) {
+                    /* skip broken unit */
+                    BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Skipping broken unit at %"PRId64"\n", st->clip_block_pos - len);
+                    st->clip_pos += len;
+                    return error;
                 }
 
                 if (st->m2ts_filter) {



More information about the libbluray-devel mailing list